Firma de solicitud basada en HMAC - Almacenamiento de la sal

11

Estoy trabajando en un proyecto (que no es de alta seguridad) que actualmente no está activo, pero podría estar activo en algún momento.

Tenemos una API REST (implementada mediante Restlet y Neo4j) que se ejecuta en un servidor y una aplicación cliente de Android.

Para mantener las cosas sin estado, debemos enviar información de autenticación junto con cada solicitud. Decidimos utilizar un enfoque basado en MAC: firmamos un conjunto de valores de encabezado, así como el cuerpo de la entidad de cada solicitud HTTP utilizando el algoritmo HMAC-SHA256. Luego ponemos ese hash junto con el nombre de usuario en el encabezado Authorization de la solicitud.

Para el secreto de HMAC, usamos una contraseña elegida por el usuario. Para hacer que las cosas sean más seguras, cambiamos la contraseña antes de usarla y almacenarla en el cliente.

Por supuesto, para que el servidor pueda validar el encabezado HMAC-SHA256, necesitamos transmitir el secreto una vez. Pero como esto solo ocurre una sola vez, no es un gran riesgo de seguridad.

El problema con esta configuración es el almacenamiento seguro de las contraseñas de los usuarios. Sé que las contraseñas nunca se deben cifrar sin usar un salt para evitar ataques a la tabla del arco iris. Pero cuando genero un salt seguro / aleatorio, un cliente que registra un usuario por primera vez no tiene manera de acceder a ese salt para generar el hash correcto.

¿Cuál sería la mejor decisión en este caso? ¿Debería simplemente almacenar las contraseñas usando un algoritmo de hashing "convencional" como SHA256 sin usar un salt? Supongo que eso sería muy negligente. También podría usar un algoritmo más seguro como bcrypt o PBKDF2 con un "dummy salt" como el nombre de usuario , un hash MD5 del nombre de usuario y un recuento de iteraciones más alto. Aunque la sal es conocida, sería muy lento y doloroso generar tablas de arco iris.

¿Bcrypt con una sal de "seguridad por oscuridad" sería lo suficientemente segura? ¿O es toda la configuración insegura y debería intercambiarse con otro método de autenticación?

    
pregunta Danilo Bargen 18.05.2012 - 00:40
fuente

3 respuestas

5

Lo más importante que debes hacer es: usar SSL . Utilice HTTPS, no HTTP.

Justificación:

  • Si usa SSL, su enfoque es razonable.

    • Detalle táctico: sugiero usar PBKDF2 con un recuento de iteración grande para generar la clave HMAC a partir de la contraseña. Puede usar un valor fijo (o un hash del nombre de usuario) como sal.

    • Es cierto que esto tendrá algunos puntos débiles: ya que almacena un hash de la contraseña en el dispositivo cliente, alguien que obtiene acceso al dispositivo móvil puede usar ataques de diccionario para intentar recuperar la contraseña, y pueden o pueden no tener éxito, dependiendo de qué tan fuerte es la contraseña. Además, cualquier persona que obtenga acceso al dispositivo móvil puede aprender la clave criptográfica, que es todo lo que se necesita para enviar solicitudes HTTP autenticadas. En muchos entornos, esta debilidad puede ser un riesgo aceptable.

  • Si no usa SSL, su esquema probablemente tendrá problemas de seguridad importantes. Cualquiera que pueda rastrear el cable podrá aprender un hash de la contraseña, y si la contraseña no es segura, podrá recuperar la contraseña del usuario mediante la búsqueda en el diccionario.

Si desea una seguridad aún mejor, aquí hay un enfoque un poco más sólido:

  • Use SSL en todo. No ensucie con HTTP sin cifrar; usa HTTPS para todo.

  • Use una clave criptográfica de fuerza completa. Haga que el servidor genere una clave criptográfica criptográfica aleatoria de 128 bits de fuerza completa para usar con HMAC. El servidor puede almacenar esta clave.

    • La primera vez que el cliente se conecte, deberá aprender esta clave criptográfica. Para hacer eso, tenga una solicitud especial donde el cliente proporcione su nombre de usuario y contraseña, y reciba la clave criptográfica en respuesta si la contraseña es correcta. (El servidor puede limitar estas solicitudes para evitar ataques de diccionario). Cuando el cliente recibe la clave criptográfica, la almacena localmente.

    • Para cada solicitud posterior, el cliente puede buscar su copia almacenada localmente de la clave criptográfica y usarla para calcular el HMAC.

    • Si el usuario inicia sesión en el sitio web desde un nuevo dispositivo, no hay problema, ese dispositivo simplemente realiza el paso de inicialización mencionado anteriormente para recuperar la clave criptográfica, entonces todo sigue funcionando.

Esto evita la necesidad de almacenar la contraseña del usuario o un hash de la contraseña del usuario en el dispositivo final. También evita ataques de búsqueda de diccionario contra la clave criptográfica; dado que la clave criptográfica es un valor totalmente aleatorio que se elige de forma aleatoria independiente de la contraseña, los ataques de búsqueda de diccionario fuera de línea contra la contraseña no tendrán éxito en la recuperación de la clave. Sin embargo, sí conserva la debilidad de que si un malvado consigue sus manos en el dispositivo cliente, podrá aprender la clave criptográfica y emitir solicitudes falsificadas. Sospecho que es lo mejor que puedes hacer, dados tus objetivos.

    
respondido por el D.W. 04.06.2012 - 07:51
fuente
4

No estoy seguro si entiendo tu problema por completo.

La sal generalmente se codifica en la representación de la cadena bcrypt.

Sin embargo, el uso del nombre de usuario como sal probablemente no funcione ya que bcrypt espera exactamente 16 bytes como sal. Así que necesitarías transformar el nombre de usuario antes. Lo que no entiendo es, ¿por qué las dos partes no tienen sal? Como dijiste, la sal es solo para prevenir ataques a la tabla del arco iris, por lo que probablemente puedas transmitirla sin que sea un problema de seguridad.

    
respondido por el lawl0r 18.05.2012 - 00:53
fuente
1

Si usa una contraseña con hash como clave HMAC, entonces su hash se convierte en el secreto compartido. Hashing (con o sin sal) protegerá la contraseña en caso de que se use en otro lugar, pero no protegerá su servicio, ya que el hash se puede usar directamente.

Creo que es mejor considerar la clave hmac como una credencial, un token. Y no puedes almacenar esos realmente seguros. Por supuesto, deberías ponerlos en un lugar seguro de todos modos.

En lugar de "enviar la contraseña una vez", le recomendaría que use algo similar a los tokens OAUTH para derivar un secreto temporal, o puede hacerlo simple y generar las "claves de acceso" en el servidor y permitir que el usuario las copie (Esto es por ejemplo lo que hace Amazon AWS). Si se trata de una cadena aleatoria, no hay peligro de filtrar las contraseñas de los usuarios (solo, de nuevo, la credencial, por supuesto).

Una alternativa sería usar algo como SRP, resultará en un secreto de maestro previo compartido que se puede usar para su clave de firma de solicitud.

    
respondido por el eckes 05.06.2014 - 23:41
fuente

Lea otras preguntas en las etiquetas