En una implementación de TOTP, ¿es necesario que exista una política de caducidad para la clave secreta del usuario?

4

Background

Estamos iniciando un proyecto para agregar un factor de autenticación adicional a nuestra aplicación web. Esto implica la creación de un token TOTP (contraseña de una sola vez basada en el tiempo) que cumple con RFC 6238 ( enlace ). Este token se entregará al usuario por SMS o correo electrónico.

Soy consciente de que este enfoque no es ideal desde el punto de vista de seguridad (por ejemplo, Eurograbber, Sandroid, Emmental). Espero dirigir a nuestra organización para evaluar otras opciones, pero mientras tanto estoy investigando las mejores prácticas para este enfoque.

Overview

  • un usuario se autentica en nuestra aplicación web con su nombre de usuario y contraseña
  • el usuario inicia alguna acción que activa una evaluación de riesgo
  • si es arriesgado:
    • saque la clave secreta encriptada del usuario de la base de datos (o genere una nueva clave aleatoria si no está)
    • use la clave secreta y la marca de tiempo actual para generar TOTP
    • TOTP se entrega al número de celular del usuario a través de SMS (o se envía por correo electrónico)
    • Mostrar pantalla de entrada TOTP
  • El usuario recibe e ingresa TOTP
    • Extraiga la clave secreta de la base de datos y genere TOTP (s)
    • valide el TOTP proporcionado contra el TOTP generado
  • si es válido, continúa con la acción original

Pregunta

¿Es necesario que haya una política de caducidad para la clave secreta del usuario?

Lógicamente, la clave secreta es incluso más segura que la contraseña del usuario (que nunca caduca). Nunca abandona nuestros sistemas (el servidor de aplicaciones y la base de datos).

Podría hacer que caduque (y genere uno nuevo) una vez al mes, o una vez cada 10 usos. Pero esto realmente solo parece dar valor si nuestra base de datos (y la clave de cifrado) se ha comprometido (en cuyo caso tenemos problemas más graves).

¿Hay mejores prácticas aquí?

Notas / Suposiciones

  • La clave secreta se generará utilizando una clase SecureRandom de Java (con reinicialización)
  • La clave secreta se cifrará cuando se almacene en la base de datos
  • Garantizaremos el uso único de un token válido.
    No se aceptará un segundo intento de un token válido (dentro de la misma ventana de tiempo).
  • La ventana de tiempo para la que es válido el token se mantendrá lo más pequeña posible. Pero debe ser lo suficientemente grande para que se entregue el token (sms / email) y para que el usuario reciba e ingrese el token.
    Probablemente comenzaremos con 90 segundos y ajustaremos según sea necesario.
  • ¿La pequeña ventana de tiempo debería evitar los ataques de fuerza bruta?
    Pero agregar un bloqueo de usuario después de decir 10 intentos de token no válidos es probablemente una buena idea.
  • Una vez que el usuario se haya autenticado con un token válido, es válido por la duración de su sesión. No será necesario que el usuario vuelva a autenticarse nuevamente más tarde.

EDIT Re: Sebastion

Consideré tu enfoque de "KISS" hace unas semanas, pero estaba planeando seguir la ruta TOTP porque proporcionaría una mayor flexibilidad para el futuro. Si alguna vez queremos utilizar Google Authenticator (o asociarnos con RSA, o Authy, etc.), estamos a mitad de camino. También simplifica un poco nuestro desarrollo, ya que la caducidad está incorporada en el algoritmo.

Pero ... ahora que retrocedo un paso, creo que su enfoque es probablemente el correcto. Diseñar en exceso y complicar en exceso para un futuro que quizás nunca suceda es un olor a código.

Una cosa que no había mencionado anteriormente era que probablemente usaría algo así como 3 ventanas de treinta segundos. Entonces, en su último punto, el período de tiempo sería de 90 segundos como máximo, o un mínimo de 60 segundos, si el token se generara al final de una ventana.

    
pregunta matt1616 29.03.2016 - 18:56
fuente

1 respuesta

4

Yo diría: No deberías tener una clave secreta en absoluto. Como tiene la intención de enviar SMS o correo electrónico a estos tokens, esto significa que no hay necesidad de una clave secreta en absoluto.

En lugar de eso, sugeriría simplemente un token aleatorio, guardarlo en la base de datos con un tiempo de caducidad (como 90 segundos a partir de ahora) y luego enviarlo. Cada intento de ingresar el token debe invalidar el token y pedirle al usuario la oportunidad de enviar un token nuevo, por lo que cada token siempre es "1 intento, exitoso o no". También agregue un Captcha para evitar que alguien lance un ataque aleatorio con la esperanza de "golpear el código correcto la primera vez solo con suerte".

No hay necesidad de usar el protocolo TOTP en absoluto, si no tiene la intención de permitir que el usuario guarde la semilla en su propio dispositivo y luego genere códigos "sin conexión".

Si, sin embargo, permite que el usuario guarde su semilla "fuera de línea", por ejemplo, para proporcionar Google Authenticator, puede ser una buena idea, pero no es práctica de la industria, reprovisionar el token a veces.

Si aún va a utilizar una "semilla" o una "clave secreta", sugeriría usar HOTP, por ejemplo, códigos basados en eventos. Porque con TOTP tendrás el problema de enviar a veces tokens ya vencidos, porque TOTP funciona como un reloj que "marca" cada X segundos, en tu caso, 90 segundos. Si el reloj está en "digamos" 85 segundos y lo envía, ya habrá expirado cuando llegue al usuario, lo que le agregará un costo innecesario y también la frustración del usuario.

    
respondido por el sebastian nielsen 30.03.2016 - 07:03
fuente

Lea otras preguntas en las etiquetas