security - ¿La mejor manera de implementar un "olvido de contraseña"?
authentication design (10)
Estoy buscando el mejor método para implementar una función de "contraseña olvidada".
Salgo con 2 ideas:
Cuando el usuario hace clic en la contraseña olvidada, el usuario debe ingresar el nombre de usuario, el 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 usa la contraseña temporal para iniciar sesión y restablece su contraseña.
Similar, pero el correo electrónico contendría un enlace para permitir al usuario restablecer su contraseña.
O alguien me puede sugerir una forma mejor y segura? También estoy pensando en enviar la contraseña o el enlace temporal, forzar al usuario a restablecer la contraseña dentro de las 24 horas o, de lo contrario, la contraseña temporal o el enlace no podrán utilizarse. ¿Como hacer eso?
Aquí hay tres enlaces muy buenos que proporcionan información sobre restablecimientos de contraseñas:
http://jtauber.com/blog/2006/03/20/account_management_patterns/
(No permita que los usuarios confirmen el uso de GET): http://www.artima.com/forums/flat.jsp?forum=106&thread=152805&start=15&msRange=15
http://fishbowl.pastiche.org/archives/docs/PasswordRecovery.pdf
Espero que ayude. Ciertamente me ayudaron a entender el problema.
Como dije, depende del nivel de seguridad requerido, sin embargo, si necesita un nivel más alto, algunas soluciones novedosas que he visto incluyen;
Mostrando la mitad de la contraseña temporal cuando se confirmó la identidad del usuario (pregunta de seguridad, dirección de correo electrónico, etc.) y luego la otra mitad se envió 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 man-in-the-middle. (Visto en UK Government Gateway)
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)
En algún punto entre estos dos extremos, la implementación de preguntas de seguridad puede ser el camino a seguir, tal como lo menciona DaveG.
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 hacker hábil que busca robar su información.
Abstenerse de enviar información personal como contraseñas e información de ingresos por correo electrónico, ya que puede convertirse en MUY EMBARAZANTE para usted y su organización si dicha información se filtró o se la robaron. Piensa seriamente en seguridad. Simplemente toma ese incidente para que caigan todos los ladrillos.
En cuanto a la recuperación de contraseñas, lea atentamente las Mejores prácticas de contraseña olvidadas .
La conclusión es que una aplicación que sigue las mejores prácticas debería permitirle al usuario restablecer su propia contraseña. Se deben usar preguntas de seguridad personal. La aplicación no debe enviar correos electrónicos, mostrar contraseñas ni establecer contraseñas temporales.
EDITAR: Enlace actualizado
Imponeré direcciones de correo electrónico únicas en todas las cuentas.
Luego, es una simple cuestión de enviar un enlace a una página temporal que le permite a la persona cambiar su contraseña. (permita 24 horas o menos)
La cuenta de correo electrónico del usuario es el más débil en este escenario.
Iré con:
- Preguntar al usuario por correo electrónico, verificar que el correo electrónico esté registrado
- Genera GUID y envíalo a ese correo electrónico
- No restablecer la contraseña todavía
- El usuario hace clic en el enlace y luego debe ingresar un nuevo pase
- Restablezca la contraseña solo después de que el usuario esté en su sitio, y haga clic en el botón Restablecer después de escribir un nuevo pase.
- Haga que ese GUID sea expirable dentro de un corto período de tiempo para hacerlo más seguro.
Nunca envíe una contraseña al usuario por correo electrónico. Incluso si se genera automáticamente. El mejor enfoque (recomendado y utilizado por SANS y otros):
- En la página de contraseña olvidada, solicite el correo electrónico / identificación de usuario y una NUEVA contraseña del usuario.
- Envíe por correo electrónico un enlace al correo electrónico almacenado para esa cuenta con un enlace de activación.
- 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, deshabilite el enlace (para que ya no cambie la contraseña).
Nunca cambie la contraseña sin el consentimiento del usuario. Significa que no envíe una nueva contraseña por correo electrónico solo porque alguien hizo clic en el enlace de contraseña olvidada y descubrió el nombre de la cuenta.
Si incluye una dirección de correo electrónico con el registro. El botón "Olvidé mi 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 de confianza.
(A menos que la base de datos esté pirateada, pero entonces nada es seguro).
Todo depende de tu sitio y del nivel de seguridad que intentas alcanzar, pero el proceso básico para una aplicación web es algo como lo siguiente:
El usuario navega a la página "Olvidé mi contraseña" e ingresa su nombre de usuario o correo electrónico (lo que sea único) para solicitar el restablecimiento de la contraseña.
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 detiene a los usuarios que reciben correos electrónicos que no solicitaron.
Busque la cuenta del usuario. Guarde una contraseña temporal (normalmente un GUID) y una marca de tiempo en el registro de la cuenta. Envíe un correo electrónico al usuario que contiene la contraseña temporal.
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.
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, luego utilice el 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 al usuario se le envía por correo electrónico una contraseña temporal que le permite cambiar su contraseña. La contraseña almacenada originalmente (¡debe ser hash!) Nunca 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.
Troy Hunt hace algunos puntos excelentes en su artículo, Todo lo que siempre quiso saber sobre la construcción de una función de restablecimiento de contraseña segura . Los extractos más relevantes son:
[T] aquí hay dos enfoques comunes:
- Genere una nueva contraseña en el servidor y envíela por correo electrónico
- Envía una URL única por correo electrónico que facilitará un proceso de reinicio
A pesar de una gran cantidad de orientación en sentido contrario, el primer punto realmente no es donde queremos estar. El problema al hacer esto es que significa que una contraseña persistente, una con la que puede volver atrás y usarla 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 hace que el bloqueo malicioso de una cuenta sea muy simple. Si conozco la dirección de correo electrónico de una persona que posee una cuenta en un sitio web, puedo cancelarla 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 que 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 exclusiva de 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 reinicio y luego volver a coincidir con un registro en el servidor junto con la cuenta del usuario confirmando que el propietario de la cuenta de correo electrónico contraseña. Por ejemplo, el token puede ser "3ce7854015cd38c862cb9e14a1ae552b" y se almacena en una tabla junto con la ID del usuario que realiza el restablecimiento y la hora a la que se generó el token (más sobre eso en un momento). Cuando se envía el correo electrónico, contiene una URL como "Reset /? Id = 3ce7854015cd38c862cb9e14a1ae552b" y cuando el usuario carga esto, la página comprueba 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 restablecimiento es limitar el token de tiempo para que el proceso de reinicio se complete dentro de una cierta duración, digamos dentro de una hora.
...
Finalmente, queremos asegurarnos de que este es un proceso de una sola vez. Una vez que se completa el proceso de reinicio, el token debe eliminarse para que la URL de restablecimiento ya no sea funcional. Al igual que en el punto anterior, esto es para garantizar que un atacante tenga una ventana muy limitada en la que puedan 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 buenos comentarios sobre cómo evitar filtraciones de información, CAPTCHA, autenticación de dos factores y, por supuesto, las mejores prácticas básicas, como el hashing de contraseñas. Creo que es importante señalar que no estoy de acuerdo con Troy en la utilidad de las preguntas de seguridad, prefiriendo el escepticismo de Bruce Schneier sobre la práctica :
El objetivo 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 el punto de vista 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 por razones de 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.
Actualización: revisada en mayo de 2013 para un mejor enfoque
- El usuario ingresa su nombre de usuario y pulsa "contraseña olvidada". También recomiendo la opción de ingresar la dirección de correo electrónico en lugar del nombre de usuario, porque a veces los nombres de usuario también se olvidan.
- El sistema tiene una tabla
password_change_requests
con las columnasID
,Time
eID
password_change_requests
. Cuando el nuevo usuario presiona el botón, se crea un registro en la tabla. La columnaTime
contiene la hora en que el usuario presionó el botón "Olvidé mi contraseña". LaID
es una cadena. Se crea una cadena aleatoria larga (por ejemplo, un GUID) y luego hash como una contraseña (que es un tema separado en sí mismo). Este hash se usa como el ''ID'' en la tabla. - 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 forgotpassword.jsp debería poder recuperar el parámetro ID. Lo siento, no sé Java, así que no puedo ser más específico. - Cuando el usuario hace clic en el enlace en el correo electrónico, se mueve a su página. La página recupera el
ID
de la URL, lo vuelve a aplicar y lo compara con la tabla. Si dicho registro está allí y no es más que, por ejemplo, 24 horas de antigüedad, se le presenta al usuario el aviso para que ingrese una nueva contraseña . - El usuario ingresa una nueva contraseña, pulsa Aceptar y todos viven felices para siempre ... ¡hasta la próxima!