¿Cómo implementar la funcionalidad de "contraseña olvidada"?

65

Para mi proyecto necesito una funcionalidad " cambiar contraseña ".

Todavía no estoy seguro de cómo implementar este tipo de funcionalidad, así que esperaba encontrar algunas "mejores prácticas" en Internet, pero no encontré nada útil que tratara todos los aspectos importantes de esta característica bastante común.

Mis propios pensamientos sobre esto son bastante directos:

Si un usuario quisiera cambiar su contraseña, podría crear un token único uniqueTokenForTheUser adjunto a una "solicitud de cambio de contraseña" que sería esencialmente el identificador de mi backend para saber si fue el usuario correcto el que envió la solicitud.

Por ejemplo, generaría / enviaría un correo electrónico a [email protected] con un enlace

http://www.example.com/changePassword?token=uniqueTokenForTheUser

uniqueTokenForTheUser se almacenaría en una tabla que se comprueba por un hilo en un cierto intervalo y elimina el registro una vez que el token ha caducado en caso de que el usuario no haya cambiado su contraseña.

Aunque esto me suena bastante sencillo, quería comprobar si había "buenas prácticas", por ejemplo. cuando se trata de la generación y eliminación de ese token en particular.

¡Cualquier sugerencia o referencia a artículos / tutoriales son bienvenidos!

Enlaces adicionales sugeridos por los comentarios:

pregunta Stefan Falk 18.03.2016 - 11:13
fuente

4 respuestas

62

Use HTTPS solo para esto, y luego veremos los detalles de la implementación.

Primero que todo, querrá protegerse contra enumeración de usuarios .

Es decir, no reveles en la página si el usuario existe o no. Esto solo debe ser revelado en el correo electrónico mismo.

En segundo lugar, querrá evitar fuga de remitentes . Asegúrese de que no haya enlaces externos o recursos externos en su enlace de destino. Una forma de mitigar esto es redirigir después de seguir el enlace inicial para que el token ya no esté en la cadena de consulta. Tenga en cuenta que si algo sale mal (por ejemplo, su base de datos está inactiva brevemente), y se muestra una plantilla de error estándar, esto puede hacer que el token se filtre en caso de que contenga alguna referencia externa.

Genere un token con 128 bits de entropía con un CSPRNG. Almacene este lado del servidor con SHA-2 para evitar que las vulnerabilidades de fuga de datos en su tabla de reinicio permitan que un atacante restablezca las contraseñas. Tenga en cuenta que la sal no es necesaria. Vence estos tokens después de un corto tiempo (por ejemplo, unas pocas horas).

Además de proporcionar el token no hash al usuario en el enlace de correo electrónico, permite al usuario navegar a la página manualmente y luego pegar el valor del token. Esto puede evitar que los valores de las cadenas de consulta se registren en el historial del navegador y, de forma predeterminada, en cualquier registro de proxy y servidor.

Opcionalmente, puede querer asegurarse de que el identificador de sesión para la sesión que inició el restablecimiento de la contraseña sea el que siguió a enlace . Esto puede ayudar a proteger una cuenta donde el atacante tiene acceso al correo electrónico del usuario (por ejemplo, configurar una regla de reenvío rápido con acceso limitado a la cuenta de correo electrónico). Sin embargo, todo lo que realmente hace es evitar que un atacante siga de manera oportunista un reinicio solicitado por el usuario: el atacante todavía podría solicitar su propio token de reinicio para la víctima si desea apuntar a su sitio en particular.

Una vez que la contraseña se haya restablecido a una de las opciones del usuario, deberá expirar el token y enviar un correo electrónico al usuario para informarle que esto sucedió en caso de que un atacante haya logrado restablecer su contraseña (sin necesariamente teniendo el control de su cuenta de correo) - defensa en profundidad. También debe rotar el identificador de sesión actual y caducar cualquier otro para esta cuenta de usuario . Esto niega la necesidad de que el usuario tenga que volver a iniciar sesión, al tiempo que borra las sesiones conducidas por un atacante, aunque a algunos usuarios les gusta que el sitio cierre la sesión para que puedan obtener una confirmación de que su contraseña se ha restablecido. La redirección a la página de inicio de sesión también brinda a algunos administradores de contraseñas la posibilidad de guardar la URL de inicio de sesión y la nueva contraseña, aunque muchos ya detectan la nueva contraseña desde la página de restablecimiento.

También puede considerar otras opciones fuera de banda para el mecanismo de restablecimiento y las notificaciones de cambios. Por ejemplo, por SMS o alertas de teléfono móvil.

    
respondido por el SilverlightFox 18.03.2016 - 13:14
fuente
10

Tu línea de pensamiento está en el camino correcto. Sin embargo, sugeriría que describa el flujo de la funcionalidad de contraseña olvidada en un paso anterior. Alguien afirma haber olvidado su contraseña, debe asegurarse de que identifica que esta persona es realmente la propietaria de la cuenta para la que iniciará el procedimiento de recuperación de contraseña.

El flujo a continuación asume un servicio donde las personas pueden registrarse, como un sitio web (en otras palabras, se puede crear una lista de correos electrónicos registrados y / o nombres de usuarios utilizando la funcionalidad de registro).

paso uno: identificar al usuario

  1. Al hacer clic en el enlace 'Oops, olvidé mi contraseña', presente al usuario un formulario donde ingrese su nombre de usuario y dirección de correo electrónico (opcionalmente, puede darles una pista sobre la dirección de correo electrónico en la forma de: 's ... .. @ o .... com ');
  2. informarles si la dirección de correo electrónico que ingresaron pertenece al nombre de usuario que ingresaron (sí o no);
  3. Si el nombre de usuario y la contraseña ingresados coinciden, continúe con los siguientes pasos.

paso dos: iniciar el procedimiento de recuperación

  1. generar un token de recuperación aleatorio (128 bits debería estar bien);
  2. almacene un hash de este token (creado mediante un algoritmo de hashing de contraseña), junto con su marca de tiempo de creación en su base de datos;
  3. envíe al usuario un correo electrónico con un enlace (que contiene el token de recuperación) a un formulario de cambio de contraseña. La URL para el formulario de cambio de contraseña debe ser HTTPS.
  4. cuando recibe la solicitud de cambio de contraseña, marca: [1]. la validez del token (usando su tiempo de creación en comparación con el tiempo actual, normalmente una ventana de tiempo de 10 minutos debería ser suficiente); [2]. si el token presentado es correcto (hash el token, compare el hash resultante con el de su base de datos, tal como lo haría con una contraseña);
  5. si todas las comprobaciones pasan, continúe con el siguiente paso.

Paso tres: actualice su contraseña

  1. destruya toda la información de 'recordarme' que pueda haber almacenado para este usuario;
  2. destruye todas las sesiones activas asociadas con este usuario;
  3. actualizar la contraseña del usuario;
  4. opcionalmente, envíe un correo electrónico a su dirección de correo electrónico para notificarles el cambio;
  5. inicia sesión el usuario.
respondido por el Jacco 18.03.2016 - 12:14
fuente
6

Usted está cerca de las mejores prácticas con su enfoque. Una pequeña adición sería:

  • Es posible que necesite que el nombre de usuario coincida con el token en lugar de simplemente deducir al usuario del token.

  • Debería usar https en lugar de http.

Las otras preguntas:

  • En cuanto a la generación: una forma habitual de generarlos es mediante el uso de UUID, pero como lo indican los comentarios, deberías usar una cadena completamente aleatoria y suficientemente larga.

  • En cuanto a la eliminación: puede limpiar los tokens antiguos que no se utilicen con regularidad, tal como sugirió. Tal vez utilice un período de tiempo que permita que el correo llegue a través de la lista habitual de correos electrónicos, por ejemplo. 15 minutos.

respondido por el Tobi Nary 18.03.2016 - 11:22
fuente
3

Algunas reflexiones sobre esto:

  • El correo electrónico es intrínsecamente inseguro. El token podría ser robado en cualquier lugar entre su servidor y la bandeja de entrada de los usuarios por un atacante. Considere utilizar otro medio de comunicación si es posible, como SMS.
  • Si vas por correo electrónico, el enlace de restauración debe estar sobre HTTPS, no HTTP. Al menos esa parte del proceso se puede cifrar.
  • Para evitar ataques de enumeración de usuarios, es posible que desee mostrar el mismo mensaje o no, la dirección de correo electrónico o nombre de usuario que el usuario ingresa o no. (Al menos, no cometa el error de mostrar el correo electrónico después de que el usuario haya ingresado solo el nombre de usuario).
  • Use un buen generador de números pseudoaleatorios y un token largo. Nadie debería ser capaz de adivinar el token. Para hacer que sea más difícil adivinar tokens, requiera que el usuario ingrese tanto el nombre de usuario como el token. Limitar el número de intentos (por nombre de usuario y / o IP) también evitará el uso de fuerza bruta. Quizás también un CAPTCHA?
  • Desea limitar el tiempo durante el cual un token es válido. El correo electrónico puede ser lento si se atasca en los filtros, pero no veo ninguna razón por la que alguien necesite más de media hora.
  • Una vez que se restaura una cuenta, finalice todas las sesiones anteriores para esa cuenta. Es posible que el usuario desee restaurar la cuenta porque se ha comprometido, y luego el atacante debe cerrar sesión.
  • ¡Solo envíe un token de uso único, y no una contraseña nueva! Las contraseñas nunca deben enviarse por correo electrónico.
  • ¡Solo permite que una ficha se use una vez! Elimínelo inmediatamente después de usarlo (incluso si el usuario no cambia realmente la contraseña).

Para obtener más información sobre el tema, recomiendo Troy Hunt .

    
respondido por el Anders 18.03.2016 - 13:05
fuente

Lea otras preguntas en las etiquetas