¿La mejor manera de implementar una "contraseña olvidada"? [cerrado]

154

Estoy buscando el mejor método para implementar una función de "contraseña olvidada".

Salgo con 2 ideas:

  1. Cuando el usuario hace clic en Olvidé mi contraseña, el usuario debe ingresar el nombre de usuario, correo electrónico y tal vez la fecha de nacimiento o apellido. Luego, se enviará un correo con contraseña temporal a la cuenta de correo electrónico del usuario. El usuario utiliza la contraseña temporal para iniciar sesión y restablece su contraseña.

  2. Similar, pero el correo electrónico contendría un enlace para permitir al usuario restablecer su contraseña.

¿O alguien puede sugerirme una forma mejor y segura? También estoy pensando en enviar la contraseña o el enlace temporal, obligar al usuario a restablecer la contraseña dentro de las 24 horas o, de lo contrario, la contraseña o el enlace temporal no serán utilizables. ¿Como hacer eso?

Zaki
fuente
Volví a etiquetar la publicación, ya que esto va más allá de JSF; probablemente obtendrá más respuestas de esa manera.
McDowell
66
@Weverever Hay una ola de "eliminemos esta pregunta cerrada porque XYZ" en meta estos meses. Solo me gustaría señalar que esta pregunta en particular no debe eliminarse, a menos que se demuestre que las soluciones son defectuosas y que su existencia literalmente duele más de lo que ayuda en el caso de la seguridad.
Félix Gagnon-Grenier
1
"Hoja de trucos" de OWASP para una estrategia de recuperación de contraseña olvidada: owasp.org/index.php/…
daiscog
El enlace sugerido por @megaflop ahora está tristemente roto, aquí está el nuevo enlace: cheatsheetseries.owasp.org/cheatsheets/…
Marco Bolis

Respuestas:

187

Actualización: revisada en mayo de 2013 para un mejor enfoque

  1. El usuario ingresa su nombre de usuario y pulsa "Olvidé mi contraseña" También recomiendo la opción de ingresar la dirección de correo electrónico en lugar del nombre de usuario, porque los nombres de usuario a veces también se olvidan.
  2. El sistema tiene una tabla password_change_requestscon las columnas ID, Timey UserID. Cuando el nuevo usuario presiona el botón, se crea un registro en la tabla. La Timecolumna contiene el momento en que el usuario presionó el botón "Olvidé mi contraseña". El IDes una cadena. Se crea una cadena larga y aleatoria (por ejemplo, un GUID) y luego se corta como una contraseña (que es un tema separado en sí mismo). Este hash se usa como 'ID' en la tabla.
  3. El sistema envía un correo electrónico al usuario que contiene un enlace. El enlace también contiene la cadena de ID original (antes del hash). El enlace será algo como esto: http://www.mysite.com/forgotpassword.jsp?ID=01234567890ABCDEF. La página olvidadapassword.jsp debería poder recuperar el parámetro ID. Lo siento, no conozco Java, así que no puedo ser más específico.
  4. Cuando el usuario hace clic en el enlace del correo electrónico, se lo traslada a su página. La página recupera el IDde la URL, lo vuelve a cifrar y lo compara con la tabla. Si dicho registro está allí y no tiene más de, por ejemplo, 24 horas, se le solicita al usuario que ingrese una nueva contraseña .
  5. El usuario ingresa una nueva contraseña, presiona OK y todos viven felices para siempre ... ¡hasta la próxima!
Vilx-
fuente
1
la forma más adecuada de implementar esto sería: enviar el token de restablecimiento de contraseña temporal como un correo electrónico en texto sin formato al usuario (pero nunca almacenarlo como texto sin formato en la base de datos), después de que el usuario ingrese esta temperatura, lo obligará inmediatamente a Vuelva a ingresar una nueva contraseña. - para los paranoicos, asegúrese de que su servidor smtp tenga ssl, de modo que sus correos que contengan información confidencial no se espíen. Para la mayoría de los casos, este enfoque es bastante seguro. si su caso requiere mayor seguridad, probablemente no debería tener usuarios que olviden sus contraseñas: S
Kaushik Gopal
66
¿Por qué generar una cadena / guid aleatoria, hacer un hash y usar el hash? ¿No es suficiente la guía?
Jeroen K
15
@jeroenk: de modo que si alguien roba su base de datos, no puede falsificar un enlace "Restablecer contraseña" y cambiar la contraseña de alguien.
Vilx-
44
Esta es esencialmente la forma descrita de restablecer correctamente una contraseña crackstation.net/hashing-security.htm#faq
TruthOf42
1
@David - Ach, quería editar la publicación, pero el tema está bloqueado. :( OK, vamos a probar de nuevo: su tabla contendrá las columnas: ID, UserID, Time, TokenHash.. Usted va a generar dos largos, cadenas aleatorias Ponga la primera cadena (el "id") en la IDcolumna; hash de la segunda (el "token" ) y coloque el hash en la TokenHashcolumna. Genere el enlace como forogotPassword.jsp?id=asdasd&token=asdasd. El token en el enlace NO tiene hash. ¿Tiene sentido ahora?
Vilx-
28

Todo depende de su sitio y del nivel de seguridad que está tratando de lograr, pero el proceso básico para una aplicación web es algo similar a lo siguiente:

  1. El usuario navega a la página 'Olvidé mi contraseña' e ingresa su nombre de usuario o correo electrónico (el que sea único) para solicitar un restablecimiento de contraseña.

  2. Opcionalmente, en esta etapa, puede confirmar la solicitud solicitando información adicional, como la respuesta a una pregunta de seguridad predefinida o su fecha de nacimiento, etc. Este nivel adicional impide que los usuarios reciban correos electrónicos que no solicitaron.

  3. Busque la cuenta del usuario. Guarde una contraseña temporal (generalmente un GUID) y una marca de tiempo en el registro de la cuenta. Enviar un correo electrónico al usuario que contiene la contraseña temporal.

  4. El usuario hace clic en el enlace que contiene la contraseña temporal y el identificador del usuario en el correo electrónico o navega a la página 'Olvidé mi contraseña' y copia y pega la contraseña temporal y su identificador. El usuario ingresa su nueva contraseña y la confirma.

  5. Busque el registro del usuario y, si la hora actual se encuentra dentro de un límite de tiempo especificado (por ejemplo, 1 hora) de la marca de tiempo guardada en el paso 2, haga un hash y guarde la nueva contraseña. (¡Obviamente solo si las contraseñas temporales coinciden!). Elimine el GUID temporal y la marca de tiempo.

El principal aquí es que el usuario recibe una contraseña temporal por correo electrónico que le permite cambiar su contraseña. La contraseña almacenada originalmente (¡debe estar cifrada!) Nunca se cambia a una contraseña temporal en caso de que el usuario la recuerde.

La contraseña original nunca se mostrará al usuario, ya que debe ser hash y desconocida.

Tenga en cuenta que este proceso depende completamente de la seguridad de la cuenta de correo electrónico del usuario. Por lo tanto, depende del nivel de seguridad que desee alcanzar. Esto suele ser suficiente para la mayoría de los sitios / aplicaciones.

David Glenn
fuente
24

Troy Hunt destaca algunos puntos excelentes en su artículo: Todo lo que siempre quiso saber sobre la creación de una función de restablecimiento de contraseña segura . Los extractos más relevantes son:

[T] aquí hay dos enfoques comunes:

  1. Genere una nueva contraseña en el servidor y envíela por correo electrónico
  2. Enviar por correo electrónico una URL única que facilitará un proceso de reinicio

A pesar de la gran cantidad de orientación en contrario, el primer punto no es realmente dónde queremos estar. El problema al hacer esto es que significa que una contraseña persistente, una con la que puede volver y usar en cualquier momento, ahora se ha enviado a través de un canal inseguro y reside en su bandeja de entrada.

...

Pero hay un gran problema más con el primer enfoque, ya que simplifica el bloqueo malicioso de una cuenta. Si conozco la dirección de correo electrónico de alguien que posee una cuenta en un sitio web, entonces puedo bloquearla cuando quiera, simplemente restableciendo su contraseña; ¡Es un ataque de denegación de servicio servido en bandeja de plata! Esta es la razón por la cual un restablecimiento es algo que solo debería ocurrir después de verificar con éxito el derecho del solicitante a hacerlo.

Cuando hablamos de una URL de restablecimiento, estamos hablando de una dirección de sitio web que es única para esta instancia específica del proceso de restablecimiento.

...

Lo que queremos hacer es crear un token único que se pueda enviar en un correo electrónico como parte de la URL de restablecimiento y luego coincidir con un registro en el servidor junto con la cuenta del usuario, lo que confirma que el propietario de la cuenta de correo electrónico es el que intenta restablecer el contraseña. Por ejemplo, el token puede ser "3ce7854015cd38c862cb9e14a1ae552b" y se almacena en una tabla junto con el ID del usuario que realiza el reinicio y la hora en que se generó el token (más sobre eso en un momento). Cuando se envía el correo electrónico, contiene una URL como "Restablecer /? Id = 3ce7854015cd38c862cb9e14a1ae552b" y cuando el usuario carga esto, la página verifica la existencia del token y, en consecuencia, confirma la identidad del usuario y permite la contraseña para ser cambiado.

...

La otra cosa que queremos hacer con una URL de reinicio es limitar el token en el tiempo para que el proceso de reinicio se complete dentro de una cierta duración, digamos en una hora.

...

Finalmente, queremos asegurarnos de que este sea un proceso único. Una vez que se completa el proceso de restablecimiento, el token debe eliminarse para que la URL de restablecimiento ya no funcione. Al igual que con el punto anterior, esto es para garantizar que un atacante tenga una ventana muy limitada en la que pueda abusar de la URL de restablecimiento. Además, por supuesto, el token ya no es necesario si el proceso de reinicio se ha completado con éxito.

Él hace muchos más puntos buenos sobre cómo evitar fugas de información, CAPTCHA, autenticación de dos factores y, por supuesto, las mejores prácticas básicas como el hash de contraseñas. Creo que es importante tener en cuenta que no estoy de acuerdo con Troy sobre la utilidad de las preguntas de seguridad, prefiriendo el escepticismo de Bruce Schneier sobre la práctica :

El punto de todas estas preguntas es el mismo: una contraseña de respaldo. Si olvida su contraseña, la pregunta secreta puede verificar su identidad para que pueda elegir otra contraseña o hacer que el sitio le envíe por correo electrónico su contraseña actual. Es una gran idea desde la perspectiva del servicio al cliente: es menos probable que un usuario olvide el nombre de su primera mascota que una contraseña aleatoria, pero es terrible para la seguridad. La respuesta a la pregunta secreta es mucho más fácil de adivinar que una buena contraseña, y la información es mucho más pública.

Dave Liepmann
fuente
1
Ese enlace tiene imágenes NSFW claras, hay un enlace para cambiar esto, pero mucha gente primero escanea una página. ¡Idea estúpida!
nik0lai
El enlace al artículo de Troy Hunt ha cambiado. Goto troyhunt.com/everything-you-ever-wanted-to-know
knarfancho
@knarfancho Corregido, gracias!
Dave Liepmann
15

Iré con:

  1. Solicite al usuario un correo electrónico, verifique que el correo electrónico esté registrado
  2. Genere GUID y envíelo a ese correo electrónico
  3. No restablezca la contraseña todavía
  4. El usuario hace clic en el enlace y luego tiene que ingresar un nuevo pase
  5. Restablezca la contraseña solo después de que el usuario esté en su sitio y haya hecho clic en el botón Restablecer después de escribir un nuevo pase.
  6. Haga que el GUID sea expirable dentro de un corto período de tiempo para hacerlo más seguro.
andres.santana
fuente
No quiero tener problemas para preguntar un? pero está relacionado con tu respuesta. ¿Cómo estás generando el GUID?
KingAndrew
2
-1 por no implementar algún tipo de hash en el enlace que le está enviando a la persona
TruthOf42
11

Cuando envíe información por correo electrónico, no será segura. Hay muchas maneras en que alguien puede obtenerlo. Sería un juego de niños para un pirata informático experto que busca robar su información.

Abstenerse de enviar cualquier información personal, como contraseñas e información de ingresos, por correo electrónico, ya que puede ser MUY EMBARAZO para usted y su organización si dicha información se filtró o fue robada. Piensa en la seguridad en serio. Solo se necesita ese incidente para que caigan todos los ladrillos.

En cuanto a la recuperación de la contraseña, lea detenidamente las mejores prácticas de Olvidé mi contraseña .

La conclusión es que una aplicación que sigue las mejores prácticas debería permitir a un usuario restablecer su propia contraseña. Deben usarse preguntas de seguridad personal. La aplicación no debe enviar correos electrónicos, mostrar contraseñas ni establecer contraseñas temporales.

EDITAR: enlace actualizado

jinsungy
fuente
Probé el enlace de Forgot Password Best Practices y obtuve un error de 500 servidores. ¿Crees que el servidor está inactivo en este momento o hay otro enlace a seguir?
KingAndrew
El enlace está muerto de nuevo.
Eric Cope
7

Como se dijo, depende del nivel de seguridad requerido, sin embargo, si necesita un nivel superior, algunas soluciones novedosas que he visto incluyen;

  • Mostrar la mitad de la contraseña temporal cuando se ha confirmado la identidad del usuario (pregunta de seguridad, dirección de correo electrónico, etc.) y luego enviar la otra mitad a la cuenta de correo electrónico. Si la cuenta de correo electrónico se ha visto comprometida, es poco probable que la misma persona también haya logrado realizar un ataque de hombre en el medio. (Visto en la puerta de enlace del gobierno del Reino Unido)

  • Confirmación de identidad por correo electrónico y otro medio, por ejemplo, un código enviado por mensaje de texto a un teléfono móvil registrado. (Visto en eBay / PayPal)

Para un punto intermedio entre estos dos extremos, la implementación de preguntas de seguridad puede ser el camino a seguir, como lo menciona DaveG.

Tom Werner
fuente
6

Si incluye una dirección de correo electrónico con el registro. El botón "olvidar contraseña" envía un correo electrónico a esa dirección de correo electrónico. Asegura que la información se envíe a un correo electrónico confiable.

(A menos que la base de datos esté pirateada, pero nada sea seguro).

Toon Krijthe
fuente
4

Haría cumplir direcciones de correo electrónico únicas en todas las cuentas.

Luego, se trata simplemente de enviar un enlace a una página temporal que permita a la persona cambiar su contraseña. (permita 24 horas o menos)

La cuenta de correo electrónico del usuario es el enlace más débil en este escenario.

Andrew Harry
fuente
2

Nunca envíe una contraseña por correo electrónico al usuario. Incluso si se genera automáticamente. El mejor enfoque (recomendado y utilizado por SANS y otros):

  1. En la página de contraseña olvidada, solicite el correo electrónico / ID de usuario y una NUEVA contraseña del usuario.
  2. Envíe un enlace al correo electrónico almacenado para esa cuenta con un enlace de activación.
  3. Cuando el usuario haga clic en ese enlace, habilite la nueva contraseña.

Si no hace clic en el enlace dentro de las 24 horas más o menos, desactívelo (para que ya no cambie la contraseña).

Nunca cambie la contraseña sin el consentimiento del usuario. Significa no enviar por correo electrónico una nueva contraseña solo porque alguien hizo clic en el enlace de contraseña olvidada y descubrió el nombre de la cuenta.

Sucuri
fuente
13
Me preocupa esta técnica. El atacante ingresa su correo electrónico y una NUEVA contraseña. El propietario de la cuenta recibe el correo electrónico, lee mal algo y hace clic en el enlace. El atacante en espera, probando una nueva contraseña cada minuto, obtiene acceso a la cuenta hasta que el propietario de la cuenta se dé cuenta de lo que sucedió y finalmente vaya a la página "Olvidé mi contraseña".
Odi - Xceed
¡Otro problema! proporcionar una nueva contraseña en el tiempo de restablecimiento de contraseña no es una buena opción. ¡Puedo olvidar la nueva contraseña nuevamente si revisé mi correo electrónico después de horas!
Yazid Erman