¿Cuál es la mejor manera de implementar "recordarme" para un sitio web? [cerrado]

510

Quiero que mi sitio web tenga una casilla de verificación en la que los usuarios puedan hacer clic para que no tengan que iniciar sesión cada vez que visiten mi sitio web. Sé que necesitaré almacenar una cookie en su computadora para implementar esto, pero ¿qué debería contener esa cookie?

Además, ¿hay errores comunes a tener en cuenta para evitar que esta cookie presente una vulnerabilidad de seguridad, que podría evitarse mientras se brinda la funcionalidad 'recordarme'?

Vort3x
fuente
55
Consulte stackoverflow.com/questions/549/… (parte II de la respuesta principal)
Frosty Z
si está utilizando ASP.NET, consulte codeproject.com/Articles/779844/Remember-Me
Believe2014
1
Hay información muy útil en Security SE ~ security.stackexchange.com/questions/19676/…
b1nary.atr0phy
La respuesta actualmente aceptada por splattne es demasiado compleja. Cree un token de +16 bytes a partir de una fuente aleatoria, diviértalo con hash y guarde el id. Luego envíe el token al usuario (codificado en base64) en una cookie HTTPS + httpOnly (para que Javascript no pueda acceder / robarlo). De esta manera, nadie puede adivinar el token o cerrar la sesión de la gente con conjeturas no válidas, pero incluso si su base de datos está pirateada, nadie puede usar los tokens en la base de datos (son hash). Entonces, solo el cliente original (o alguien que roba el token de la tienda del navegador de alguna manera) puede usarlo.
Xeoncross

Respuestas:

536

Mejor práctica de cookies de inicio de sesión persistente mejorada

Puede utilizar esta estrategia descrita aquí como práctica recomendada (2006) o una estrategia actualizada descrita aquí (2015):

  1. Cuando el usuario inicia sesión exitosamente con Remember Me marcado, se emite una cookie de inicio de sesión además de la cookie de administración de sesión estándar.
  2. La cookie de inicio de sesión contiene un identificador de serie y un token . La serie y el token son números aleatorios indiscutibles de un espacio adecuadamente grande. Ambos se almacenan juntos en una tabla de base de datos, el token está en hash (sha256 está bien).
  3. Cuando un usuario que no ha iniciado sesión visita el sitio y presenta una cookie de inicio de sesión, el identificador de serie se busca en la base de datos .
    1. Si el identificador de serie está presente y el hash del token coincide con el hash de ese identificador de serie, el usuario se considera autenticado . Un nuevo token se genera, un nuevo hash para el token se almacena el registro antiguo, y una nueva cookie de inicio de sesión se emite al usuario (que está bien volver a utilizar el Identificador de la serie ).
    2. Si la serie está presente pero el token no coincide, se supone un robo . El usuario recibe una advertencia fuertemente redactada y se eliminan todas las sesiones recordadas del usuario.
    3. Si el nombre de usuario y la serie no están presentes, se ignora la cookie de inicio de sesión .

Este enfoque proporciona defensa en profundidad. Si alguien logra filtrar la tabla de la base de datos, no le da al atacante una puerta abierta para hacerse pasar por usuarios.

splattne
fuente
20
vea también: stackoverflow.com/questions/549/… NO debería leer la versión 'mejorada'
Jacco
8
El problema con esto es que expones el nombre de usuario en la cookie, aunque esto es lo que hace Gmail. ¿Por qué necesita una ID de serie y un token? ¿No estaría bien una ficha más grande?
Dan Rosenstark el
10
Además, con respecto a este modelo, es para evitar que un atacante robe y luego coloque la cookie en su computadora y elimine la cookie de la computadora pirateada. ¿Su computadora se autenticaría y actualizaría según sea necesario sin que la computadora pirateada lo supiera? El único cambio sería que el usuario de las computadoras pirateadas tendría que iniciar sesión nuevamente y configurar Recordarme. Si el usuario pirateado reconoce o no esto sería incierto.
24
@HiroProtagonist El identificador de serie es para evitar un ataque DoS. Sin él, podría escribir rápidamente un script que golpee su sitio con cada nombre de usuario y un token no válido, cerrando la sesión de todos en su sitio.
Chris Moschini
66
Esta solución es INCORRECTA, no maneja la moneda: si llegan dos solicitudes de autenticación de recordarme al mismo tiempo, con la misma cookie de recordar, la primera tiene éxito y cambia el token, la segunda causa una autenticación sin éxito, y una falsa alarma (porque el token ya ha sido cambiado por la primera solicitud). (Esta situación puede ocurrir cuando el navegador se pone en marcha, y el sitio se restablece en dos pestañas del navegador.)
slobo
9

Almacenaría una identificación de usuario y un token. Cuando el usuario regrese al sitio, compare esos dos datos con algo persistente como una entrada de la base de datos.

En cuanto a la seguridad, simplemente no coloque nada que permita que alguien modifique la cookie para obtener beneficios adicionales. Por ejemplo, no almacene sus grupos de usuarios o su contraseña. Cualquier cosa que pueda modificarse que eluda su seguridad no debe almacenarse en la cookie.

dragonmantank
fuente
8

Almacene su UserId y un RememberMeToken. Cuando inicien sesión con recordarme marcado, genere un nuevo RememberMeToken (que invalida cualquier otra máquina que esté marcada, recuérdame).

Cuando regresen, búsquelos con el token recordarme y asegúrese de que el ID de usuario coincida.

jonnii
fuente
Esto puede ser forzado en segundos. Solo estableceré mi user_id en 1 y fuerza bruta todos los tokens. Me dará acceso en segundos
un amigo el
4

Investigando sesiones persistentes, descubrí que simplemente no vale la pena el riesgo de seguridad. Úselo si es absolutamente necesario, pero debe considerar una sesión tan débilmente autenticada y forzar un nuevo inicio de sesión para cualquier cosa que pueda ser de valor para un atacante.

Por supuesto, la razón es que sus cookies que contienen su sesión persistente se roban tan fácilmente.

4 formas de robar sus cookies (de un comentario de Jens Roland en la página @splattnebasado en su respuesta):

  1. Al interceptarlo a través de una línea no segura (rastreo de paquetes / secuestro de sesión)
  2. Accediendo directamente al navegador del usuario (a través de malware o acceso físico a la caja)
  3. Al leerlo desde la base de datos del servidor (probablemente inyección de SQL, pero podría ser cualquier cosa)
  4. Por un hack XSS (o un exploit similar del lado del cliente)
Jarl
fuente
104
1. HTTPS está diseñado para evitar esto. 2. Mantenerse conectado no es el problema de seguridad aquí, tiene problemas más grandes. 3. Igual que 2. 4. Esto puede evitarse mediante una política de control de acceso y un buen saneamiento de los insumos; Si no sigue estos pasos, nuevamente tiene problemas más grandes que Mantenerse conectado.
Chris Moschini