¿Puede el hashing del lado del cliente reducir el riesgo de denegación de servicio con hashes lentos?

28

Al almacenar las contraseñas de los usuarios que necesita verificar (pero no usar como texto sin formato), el estado actual de la técnica es:

  1. hash la contraseña
  2. Use una sal
  3. Utilice una función hash lenta: bcrypt, scrypt, etc.

Esto proporciona la mejor protección posible contra un atacante que ha robado la base de datos de contraseñas. No resuelve otros problemas como phishing, malware, reutilización de contraseñas, etc.

Pero hay un problema restante: la función hash lenta puede permitir un ataque de denegación de servicio . Una sola solicitud quema una gran cantidad de CPU, lo que hace posible un DOS con un número relativamente pequeño de solicitudes simultáneas, lo que dificulta el uso de defensas como la limitación de IP.

Dada la mejora en el rendimiento de JavaScript en los navegadores, ahora puede tener sentido hacerlo en el navegador. Supongo que aquí el sitio está utilizando SSL, por lo que el JavaScript se entrega de forma segura. Si no está utilizando SSL, es poco probable que el uso de una función hash lenta sea una prioridad para usted. Hay al menos una implementación de JavaScript de bcrypt. Pero usar esto de una manera simple presentaría dos problemas:

  1. El cliente necesita obtener el salt del servidor. Esto introduce la latencia en el inicio de sesión y, a menos que se tenga cuidado, puede revelar si existe una cuenta de usuario en particular.
  2. Si el hashing se realiza exclusivamente en el cliente, se pierden los beneficios de almacenar hashes. Al atacante que haya robado los hashes de contraseña, simplemente puede iniciar sesión con los hashes.

Sin embargo, creo que hay soluciones aceptables para ambos problemas:

  1. La sal se puede generar como hash (server_salt + user_name), donde server_salt es un número aleatorio que es único para el servidor, público y el mismo para todos los usuarios. El hash resultante parece tener las propiedades requeridas de una sal.
  2. El servidor debe realizar una sola operación hash rápida en el hash que recibe. Como ejemplo: el servidor almacena SHA-256 (bcrypt (salt, contraseña)). El cliente envía bcrypt (sal, contraseña), luego el servidor aplica SHA-256 y verifica el hash. Esto NO permite que un atacante realice un ataque rápido de fuerza bruta sin conexión. Pueden hacer una fuerza bruta rápida de SHA-256 (contraseña) porque la contraseña tiene una cantidad limitada de entropía: 2 ^ 50 o 2 ^ 60 o menos. Pero un bcrypt (sal, contraseña) de 128 bits tiene entropía o 2 ^ 128, por lo que no pueden forzarlo fácilmente.

Entonces, ¿es este un enfoque razonable y seguro?

Soy consciente de los consejos generales para "no enrollar tu propio cripto". Sin embargo, en este caso, estoy tratando de resolver un problema que no se resuelve con criptografía comercial. Para obtener credibilidad básica, esto se ha visto en John Steven ( un experto reconocido en el campo) con un resultado positivo de un análisis "breve".

    
pregunta paj28 25.05.2014 - 20:31
fuente

2 respuestas

23

El uso de servername + username como salt (o un hash del mismo) no es ideal, ya que conduce a la reutilización de sal cuando cambia su contraseña (ya que mantiene su nombre y aún habla con el mismo servidor). Otro método es obtener la sal del servidor como un paso preparatorio; esto implica un viaje de ida y vuelta adicional entre el cliente y el servidor, y también significa que al servidor le resultaría más difícil ocultar si un nombre de usuario determinado existe o no (pero en la práctica no importa mucho).

Lo que describe es una idea bien conocida, generalmente llamada alivio del servidor , que se puede aplicar a cualquier función de hashing de contraseñas de la forma que describe:

  • El cliente obtiene (o calcula) la sal.
  • El cliente calcula el valor hash lento con sal V y lo envía como contraseña.
  • El servidor almacena h (V) para una función hash rápida h , y la usa para verificar el valor V del cliente.

Esto es seguro. El principal inconveniente es que el hash lento irá a la velocidad del cliente, por lo que el número de iteraciones tendrá que reducirse, posiblemente de manera considerable si el cliente es computacionalmente débil, como es el caso de cualquier cosa que involucre Javascript. Si el sistema debe funcionar con un navegador en un teléfono inteligente no tan reciente, entonces el recuento de iteraciones deberá ser de 10 a 100 veces más pequeño que lo que se podría hacer en el servidor, lo que implica una reducción correspondiente en la resistencia a la fuerza bruta (en En caso de que el atacante robe los valores de hash almacenados en el servidor).

Así que eso es un compromiso: debido a que las descargas de servidores ocupados funcionan en los clientes, puede usar un mayor número de iteraciones sin que se ahogue bajo la carga; pero como los clientes son débiles, el recuento de iteraciones debe reducirse, generalmente mucho más de lo que se incrementó gracias a la descarga; Esto significa que la construcción no merece la pena. Por lo general.

Por supuesto, si los clientes son computacionalmente fuertes, por ejemplo. Esta es una aplicación de código nativo en una máquina de juego, entonces el alivio del servidor es una buena idea y se verá como lo describe.

Otra posibilidad es descargar el trabajo a otro sistema de terceros, por ejemplo. otros clientes (ya conectados): esto se puede hacer de forma segura si la función hash incluye las estructuras matemáticas necesarias. Dicha descarga se conoce como delegación . Que yo sepa, la delegación se ofrece mediante una única función de hashing de contraseña, llamada Makwa (vea especificación ), uno de los candidatos de la actual Competencia de hash de contraseña .

    
respondido por el Tom Leek 25.05.2014 - 21:20
fuente
1

Creo que la mayor preocupación acerca de este enfoque es que mueve un procedimiento de seguridad que usted ha determinado que es importante fuera de sus servidores y en los navegadores web de los usuarios. Mientras que normalmente todo debería funcionar como se espera, no tiene una manera real de verificar que la contraseña haya sido bloqueada con bcrypt antes de que se le envíe. Por lo tanto, si se modifica el JavaScript del lado del cliente, aún puede terminar con solo un hash SHA256 de "123456" en su servidor.

Claro, puede verificar el formato de los datos enviados desde el cliente para asegurarse de que parece que se ha copiado con bcrypt, pero no está seguro de haber completado la operación deseada.

Ese no es un modelo de seguridad ideal, pero a pesar de eso creo que las amenazas a este sistema aún son bastante manejables. Y estaría por delante de esos sitios que no hacen hash o hash con MD5 simple.

    
respondido por el PwdRsch 25.05.2014 - 21:23
fuente

Lea otras preguntas en las etiquetas