¿Cómo escribir una implementación TOTP sólida como una roca?

3

Actualmente estoy escribiendo una implementación de TOTP en PHP (pero esto también se aplica a otros lenguajes) y, por supuesto, quiero que sea lo más seguro posible, ¿qué se debe considerar?

Después de leer el RFC 6238 correspondiente y RFC 4226 mi implementación actualmente se ve así:

  • Cada código utilizado solo se incluye en la lista negra durante 2 minutos, independientemente de si tuvo éxito o no
  • El secreto es generado por un generador de números aleatorios seguro
  • El código QR se genera en mi máquina y no se entrega a proveedores terceros
  • Se requiere ingresar un reCaptcha para evitar ataques de fuerza bruta
  • Los códigos se validan mediante una función de comparación resistente al ataque de tiempo
  • Se verifican un total de 5 códigos (el actual, los dos últimos y los dos siguientes)
  • Se genera un único código de rescate de 16 caracteres (mediante un generador de números aleatorios seguro) y solo se muestra una vez después de la activación exitosa, no puede ser recuperado por el usuario posteriormente
  • A los usuarios se les pregunta solo una vez cada siete días en una máquina conocida (configurando una cookie)
  • Los códigos de Secrets y Rescue se almacenan sin cifrar en la base de datos, pero esto no debería ser un problema, ya que el script debe descifrarlos de todos modos

¿Me faltan algunos importantes? ¿Algunos de los puntos son una mala decisión?

    
pregunta TimWolla 02.01.2014 - 20:30
fuente

3 respuestas

2
  

A los usuarios se les pregunta solo una vez cada siete días en una máquina conocida (configurando una cookie)

Deberá tener mucho cuidado aquí, ya que una cookie de este tipo sería efectivamente una puerta trasera que evita el requisito de 2 factores. Un atacante tendría que esperar hasta que un usuario se autentique, robe su cookie, y ahora ya no tiene que preocuparse por la autenticación de 2 factores. Puede reforzar esto vinculando la cookie a la dirección IP (altamente no confiable, ya que las personas saltan de proveedores inalámbricos todo el tiempo), a una cadena de identificación del navegador (muy fácil de anular), o a una región GeoIP (más confiable que a una IP, pero también menos seguro y no a prueba de errores).

Para su información, escribí una implementación Python / CGI TOTP ( enlace ), que acepta llamadas REST simples. Puede ser algo que puede usar en lugar de reescribirlo completamente en PHP.

    
respondido por el mricon 02.01.2014 - 21:39
fuente
3

Uno puede argumentar que los secretos no cifrados, almacenados "como están" en la base de datos, pueden ser una presa fácil para los ataques de inyección de SQL. Aunque conceptualmente los secretos son accesibles desde el servidor en ejecución, puede valer la pena protegerlos un poco más, de modo que los atacantes tengan que ir más allá de la etapa de "SQL personalizado". Por ejemplo, en lugar de almacenar el secreto S y el código de rescate C para cada usuario en la base de datos, almacene para cada usuario un valor aleatorio R y calcular el secreto S y el código de rescate C con HMAC sobre R , usando una clave secreta de todo el servidor almacenado en un archivo de configuración, no en la base de datos. Use HMAC / SHA-1 sobre "secret || R " (concatenación de la cadena ASCII " secret " y el valor aleatorio R ) para obtener el secreto del usuario real S ; para el código de rescate, use HMAC / SHA-1 sobre "rescue || R ".

Otras personas pueden argumentar que PHP no es el mejor lenguaje para la criptografía. De hecho, los lenguajes de alto nivel no son adecuados para cosas como "funciones de comparación de tiempo constante". Para obtener un control real sobre los problemas de implementación (todas las fugas de los canales laterales, incluida la sincronización), se recomienda un lenguaje de nivel inferior (incluso C # o Java serían "de nivel inferior" en ese sentido).

La lista negra de todos los códigos enviados puede aumentar la vulnerabilidad a DoS; alguien puede enviarte un montón de solicitudes para que tu servidor recuerde muchos códigos en lista negra. Del mismo modo, su descripción no parece incluir medidas de prevención de nuevo, como spam pesado. Es posible que desee, al menos, negarse a hablar con direcciones IP que le hayan enviado más de diez solicitudes en los últimos diez segundos aproximadamente.

Implementar la criptografía correctamente es difícil; hacerlo nuevamente significa tomar riesgos adicionales de problemas relacionados con la implementación. Hacer tu propio código es una gran pedagogía; pero si desea utilizar el código en producción, entonces tal vez debería intentar primero ver si no existe una implementación que ya se ajuste a su factura.

    
respondido por el Tom Leek 02.01.2014 - 21:11
fuente
0
  
  • Cada código utilizado solo se incluye en la lista negra durante 2 minutos, independientemente de si tuvo éxito o no
  •   
  • Se verifican un total de 5 códigos (el actual, los dos últimos y los dos siguientes)
  •   

Es un hilo antiguo, pero en su caso, los códigos utilizados deben estar en la lista negra al menos para 6 (the codes that you allow + 1) * time step (por ejemplo, 30 o 60 segundos) que utilizó para generar el código. De lo contrario, todavía será posible que alguien se autentique con un código que ya se usó.

Es importante si su transporte no está asegurado y si alguien puede escuchar a escondidas

    
respondido por el Saravanan M 30.01.2017 - 20:23
fuente

Lea otras preguntas en las etiquetas