Saltar al contenido

Hash de contraseña: agregue sal + pimienta o ¿la sal es suficiente?

Solución:

En algunas circunstancias, los pimientos pueden ser útiles.

Como ejemplo típico, digamos está creando una aplicación web. Consiste en el código de la aplicación web (que se ejecuta en algún marco de aplicación web, ASP.NET MVC, Pyramid en Python, no importa) y una base de datos SQL para el almacenamiento. La aplicación web y la base de datos SQL ejecutar en diferentes servidores físicos.

El ataque más común contra la base de datos es un exitoso ataque de inyección SQL. Este tipo de ataque no necesariamente obtiene acceso al código de su aplicación web, porque la aplicación web se ejecuta en un servidor e ID de usuario diferentes.

Necesita almacenar las contraseñas de forma segura en la base de datos y cree algo en forma de:

$hashed_password = hash( $salt . $password )

dónde $salt se almacena en texto plano en la base de datos, junto con el $hashed_password representación y elegido al azar para cada contraseña nueva o modificada.

los el aspecto más importante de cada esquema de hash de contraseñas es eso hash es un lento función hash criptográficamente segura, consulte https://security.stackexchange.com/a/31846/10727 para obtener más conocimientos básicos.

La pregunta es entonces, dado que es casi nulo esfuerzo agregar un valor constante al código de la aplicación, y que el código de la aplicación normalmente no estar comprometido durante un ataque de inyección de SQL, ¿es lo siguiente sustancialmente mejor que lo anterior?

$hashed_password = hash( $pepper . $salt . $password )

dónde $salt se almacena en texto plano en la base de datos, y $pepper es una constante almacenada en texto plano en el código de la aplicación (o configuración si el código se usa en varios servidores o la fuente es pública).

Añadiendo esto $pepper es fácil: solo está creando una constante en su código, ingresando un gran valor aleatorio criptográficamente seguro (por ejemplo, 32 bytes de / dev / urandom codificado en hexadecimal o base64) y usando esa constante en la función hash de contraseña. Si tiene usuarios existentes, necesita una estrategia de migración, por ejemplo, vuelva a procesar la contraseña en el próximo inicio de sesión y almacene un número de versión de la estrategia de hash de contraseña junto con el hash.

Respuesta:

Utilizando el $pepper lo hace agregar a la fuerza del hash de la contraseña si compromiso de la base de datos No implica compromiso de la aplicación. Sin el conocimiento de la pimienta, las contraseñas permanecen completamente seguras. Debido a la sal específica de la contraseña, ni siquiera puede averiguar si dos contraseñas en la base de datos son iguales o no.

La razon es que hash($pepper . $salt . $password) construir efectivamente una función pseudoaleatoria con $pepper como clave y $salt.$password como entrada (para cuerdo hash candidatos como PBKDF2 con SHA *, bcrypt o scrypt). Dos de las garantías de una función pseudoaleatoria son que no se puede deducir la entrada de la salida con una clave secreta ni la salida de la entrada sin el conocimiento de la clave. Esto suena muy parecido a la propiedad unidireccional de las funciones hash, pero la diferencia radica en el hecho de que con valores de entropía baja como las contraseñas, puede enumerar efectivamente todos los valores posibles y calcular las imágenes bajo la función hash pública y así encontrar el valor cuyo la imagen coincide con la imagen previa. Con una función pseudoaleatoria no puede hacerlo sin la clave (es decir, sin la pimienta) ya que ni siquiera puede calcular la imagen de un valor único sin la clave.

El importante papel de la $salt en esta configuración entra en juego si tiene acceso a la base de datos durante un tiempo prolongado y todavía puede trabajar normalmente con la aplicación desde el exterior. Sin el $salt puede establecer la contraseña de una cuenta que controla a un valor conocido $passwordKnown y compare el hash con la contraseña de una contraseña desconocida $passwordSecret. Como hash($pepper . $passwordKnown)==hash($pepper . $passwordSecret) si y solo si $passwordKnown==$passwordSecret puede comparar una contraseña desconocida con cualquier valor elegido (como tecnicismo, asumo la resistencia a la colisión de la función hash). Pero con la sal que obtienes hash($pepper . $salt1 . $passwordKnown)==hash($pepper . $salt2 . $passwordSecret) si y solo si $salt1 . $passwordKnown == $salt2 . $passwordSecret y como $salt1 y $salt2 fueron elegidos al azar para $passwordKnown y respectivamente $passwordSecret las sales nunca serán las mismas (asumiendo valores aleatorios lo suficientemente grandes como 256 bits) y, por lo tanto, ya no puede comparar las contraseñas entre sí.

(Nota: usar un salt es solo la mitad del trabajo; también debe hacer que la función hash sea lenta, de modo que atacar una sola contraseña de baja entropía aún sea difícil. La lentitud generalmente se logra a través de múltiples iteraciones o hash de la concatenación de 10000 copias de la sal y la contraseña).

Lo que hace su “pimienta” es que transforma el hachís en un MAC. Hacer un MAC bueno y seguro a partir de una función hash no es fácil, por lo que será mejor que use HMAC en lugar de una construcción casera (la forma teórica de decirlo es que una función hash resistente a colisiones no es necesariamente indistinguible de un oráculo aleatorio ).

Con un MAC, mayo ganar algo de seguridad en el siguiente sentido: posiblemente, el acceso de lectura a la base de datos por parte del atacante podría dejar de ser un problema real. La tecla MAC (la “pimienta”) puede concentrado la necesidad de confidencialidad. Sin embargo, esto depende de que MAC sea también una función unidireccional, que es una propiedad que obtendrá de muchas construcciones de MAC (incluido HMAC) pero que no está realmente garantizada criptográficamente hablando (hay sutilezas).

El “pimiento” implica que tiene una clave para administrar, incluido el almacenamiento seguro de una manera que resiste los reinicios. Una clave es pequeña y cabe en la RAM, pero, debido a los requisitos de almacenamiento, no está claro si realmente mejora seguridad. Un atacante que puede leer toda la base de datos normalmente también puede leer todo el disco duro, incluido cualquier archivo “protegido”. El tamaño pequeño de la clave puede permitir algunas configuraciones avanzadas, por ejemplo, la clave se almacena en tarjetas inteligentes que se utilizan en el momento del arranque pero que no se dejan conectadas después. En resumen, si vale la pena el esfuerzo con pimienta depende completamente del contexto; en general, recomendaría no hacerlo, para evitar la complejidad adicional.

Me gustaría señalar lo que realmente puede hacer un pimiento.

¿Cuándo ayuda un pimiento?

Como los demás ya señalaron, agregar un pimiento es solo una ventaja, siempre que el atacante tenga acceso a los valores hash en la base de datos, pero no tenga control sobre el servidor y, por lo tanto, no tenga no conozco la pimienta. Esto es típico de la inyección de SQL, probablemente uno de los ataques más utilizados, porque es muy fácil de hacer.

¿Qué mejora un pimiento?

$hashValue = bcrypt('12345', $cost, $salt);

Puede obtener esta contraseña fácilmente con un ataque de diccionario, incluso si utilizó correctamente una función de derivación de clave lenta. Ponga las contraseñas más utilizadas en un diccionario y use la fuerza bruta con estas contraseñas débiles. Es muy probable que encontremos la contraseña en (demasiados) casos.

$hashValue = bcrypt('12345anm8e3M-83*2cQ1mlZaU', $cost, $salt);

Con la pimienta, la contraseña débil crece en longitud, ahora contiene caracteres especiales y, lo que es más importante, no la encontrará en ningún diccionario. Entonces, mientras el pimiento permanezca en secreto, lo hace prevenir ataques de diccionario, en este caso puede proteger contraseñas débiles.

Editar:

Hay una mejor manera de agregar una clave del lado del servidor que usarla como pimiento. Con un pimiento, un atacante debe obtener privilegios adicionales en el servidor para obtener la clave. La misma ventaja que obtenemos calculando el hash primero y luego cifrando el hash con la clave del lado del servidor (cifrado bidireccional). Esto nos da la opción de cambiar la clave siempre que sea necesario.

$hash = bcrypt($passwort, $salt);
$encryptedHash = encrypt($hash, $serverSideKey);
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *