Almacena de forma segura las credenciales básicas de autenticación en la base de datos

2

Necesito poder comunicarme con un servicio API REST y almacenar el par de nombre de usuario / contraseña en una base de datos.

El cliente habla con la API desde un servidor dentro de nuestra DMZ, pero obtiene las credenciales de una base de datos fuera de la DMZ dentro de la red. Me gustaría poder hacer esto más seguro para que, si el servidor estuviera comprometido, sería difícil acceder a las credenciales.

¿Cuál es el mejor enfoque para almacenar las credenciales de forma segura? No puedo usar una sal & mecanismo de hashing porque la API exige el par de nombre de usuario / contraseña como texto sin formato y controlan el proceso de autenticación.

Plataforma e idiomas en uso: Windows/.NET/C#

    
pregunta user183872 06.09.2016 - 16:05
fuente

3 respuestas

1

Una solución

Abordar solo el problema relacionado con el almacenamiento seguro de credenciales. Siempre existe un riesgo, ya que la clave de descifrado todavía tendrá que almacenarse en algún lugar.

Por ejemplo, podría usar OpenSSL para cifrar una cadena de texto y luego tenerlo almacenado en la base de datos en el servidor "inseguro". Tendrías que usar un método de cifrado reversible para esto también.

Tal tarea podría lograrse con un simple script PHP:

openssl_encrypt(PLAINTEXT, ENCRYPTION_METHOD, KEY, OPENSSL_OPTIONS, INITIALIZATION_VECTOR)

Así en contexto, por ejemplo. (Asegúrese de que también agrega 16 bytes de relleno antes del cifrado y elimine 16 bytes de relleno en el descifrado; esto puede eliminarse especificando opciones específicas de OpenSSL; sin embargo, para mayor facilidad, solo puede agregar y eliminar el relleno. Además, esto también puede actuar como cierto grado de ofuscación, en cierta medida, en este ejemplo, se han usado 16 '=' caracteres. Esto también puede depender en gran medida de cómo esté configurada su instalación de OpenSSL; . Llámelo un toque de 'sal' si lo haría ...)

openssl_encrypt("================username:password", "aes-128-cbc", "StRoNGeNcrYptIOnKey", 0, "16ByteIV--Random")

Ejecutar lo anterior produciría algo similar a:

+VUYZEh3FII7HRvJ8Qm8glERsgfsSKG9tE8Zyr2EJLL+9VaF7+41q/MeL8R1++L1

A continuación, puede ejecutar el descifrado posterior:

openssl_decrypt("+VUYZEh3FII7HRvJ8Qm8glERsgfsSKG9tE8Zyr2EJLL+9VaF7+41q/MeL8R1++L1", "aes-128-cbc", "StRoNGeNcrYptIOnKey", 0, "16ByteIV--Random");

Produciendo:

================username:password

Hay una gran variedad de algoritmos de cifrado que se pueden usar. También hay un artículo en PHP.net que muestra cómo se puede lograr esto, y también incluye Linux Ejemplos de CLI, si desea hacer esto también a través de scripts de bash.

TENER EN CUENTA

Aún tendrá que mantener una copia de texto simple de la clave de cifrado en su dispositivo si se trata de un proceso automatizado, que puede no ser ideal, ni sería recomendable. No hay nada que le impida utilizar este enfoque y almacenar los datos cifrados en su servidor externo, sin embargo, tómese un momento para sopesar las implicaciones de seguridad de almacenar una contraseña en texto sin formato en un servidor.

Si te sientes neurótico

Incluso podría cifrar las credenciales una vez con un algoritmo y luego volver a cifrar el texto cifrado con otro algoritmo completamente diferente.

Depende de usted, depende de la seguridad de los datos y de la cantidad de tiempo de CPU / justificación / etc que desee dedicar a esto.

Relato corto

Necesita una solución de cifrado reversible si desea poder recuperar texto sin formato de texto cifrado y viceversa.

    
respondido por el Yan McCabe-Costa 06.09.2016 - 16:55
fuente
1

Creo que la tarea es muy difícil. Su servidor tiene acceso a las credenciales. Esto significa que el proceso en ejecución tiene todos los privilegios que necesita

  1. recupere los datos relevantes de una base de datos (ya sea encriptada o no)
  2. acceder a elementos relevantes para descifrar (por ejemplo, una clave en el sistema de archivos que se usa para el cifrado / descifrado)

Si su servidor está comprometido, esto significa que alguien inyecta código en el servidor y obtiene un shell al menos como el usuario que ejecuta el proceso (como www-data para apache). (Si es peor que eso, entonces se acabó el juego de todos modos).

Esto significa que el atacante tiene la posibilidad de acceder a la base de datos y probablemente también acceder a la clave de cifrado.

Dicho esto, puedo imaginar dos formas de fortalecer el sistema.

Clave de cifrado que pertenece a la raíz. Podría escribir un servidor que se inicie como raíz y luego ejecute los procesos de trabajo secundarios que realmente hacen el trabajo. Lo primero que hace cada niño es cambiar de usuario a www-data. Apache funciona de esta manera. La clave de cifrado se encuentra en el sistema de archivos en un archivo con permisos 0400 (acceso de lectura solo para root). El despachador lee la clave justo después del inicio. Después de que los niños se bifurcan, entrega la clave de cifrado a los niños sobre algún método de comunicación entre procesos. Si uno de los procesos secundarios está comprometido, el proceso que se ejecuta como www-data no puede acceder a la clave en el sistema de archivos (solo la raíz puede). El atacante tendría que encontrar una manera de inspeccionar la memoria del proceso para encontrar la clave. No es imposible, pero definitivamente no es nada para principiantes.

Almacenamiento y cifrado separados. Supongamos que sus clientes necesitan autenticarse en el servidor (debería ser así de todos modos). A continuación, puede separar las tareas de almacenamiento y cifrado. Un servicio lee la contraseña cifrada y la envía de vuelta al cliente. Un segundo servicio, que puede ejecutarse en el mismo cuadro pero como un usuario diferente realiza el descifrado. Así que el cliente necesita realizar 2 llamadas. ¿Qué pasa si uno de los servicios está comprometido? Luego puede cualquiera de ellos descifrar una contraseña encriptada xor para acceder a los registros encriptados en la base de datos. El punto crucial aquí es que debe asegurarse de que digamos que el primer servicio comprometido no puede enviar la contraseña cifrada al segundo servicio. Pero eso no debería ser posible si el cliente se autentica (y ninguno de estos 2 servidores debe conocer las credenciales de texto claro).

Esperando los comentarios de la comunidad.

    
respondido por el kaidentity 06.10.2016 - 18:09
fuente
1

La mejor opción es asegurar el servicio REST con un certificado de cliente (en lugar de las credenciales básicas de autenticación), si esa es una opción. Por lo general, esto se puede lograr sin cambiar el código del servicio; por lo general, todo se puede hacer a través de la configuración de la plataforma del servidor web.

Si esto no es posible, aún podría proteger las credenciales básicas de autenticación con la misma seguridad que protege su almacén de certificados, como este:

  1. Genere un certificado para usted mismo, e impórtelo (incluida la clave privada) en un almacén de certificados apropiado en el servidor, probablemente un almacén de certificados que sea privado para el proceso del servidor web. No mencionaste en qué plataforma estás. Si está en Windows, puede colocar el certificado en el almacén de usuarios para la cuenta de servicio de dominio de la aplicación.

  2. Cifre las credenciales básicas de autenticación utilizando la clave pública del certificado. Almacene las credenciales cifradas en su base de datos, archivo de configuración o cualquier cosa que use su cliente REST.

  3. Cuando necesite llamar al servicio REST, recupere la clave privada del certificado del almacén de certificados y use la clave privada para descifrar las credenciales.

En teoría, esto es una especie de seguridad por oscuridad, pero tiene la ventaja de aprovechar todo el fortalecimiento del sistema que se realiza en las tiendas de certificados, que obviamente son muy sensibles. Ahora, tal vez un hacker pueda acceder a esa tienda de certificados, pero si tiene éxito en eso, es probable que tenga problemas mucho mayores.

Este artículo aquí parece contener todos los detalles que ' d necesita.

    
respondido por el John Wu 06.12.2016 - 02:45
fuente

Lea otras preguntas en las etiquetas