He escrito extensamente sobre seguro Inicio de sesión y casillas de verificación "Recuérdame" . La respuesta aceptada no es incorrecta, pero diría que es un poco más complicada en un aspecto de lo que debe ser, y descuida un área donde se necesita un poco más de complejidad.
genere y almacene un archivo nonce en el lado del servidor, haga un hash con el nombre de usuario y otra información (por ejemplo, la dirección IP del cliente, el nombre de computadora, la marca de tiempo, cosas similares) y envíe eso en la cookie. El nonce debe almacenarse en la base de datos, junto con la fecha de caducidad, y ambos deben verificarse cuando vuelva la cookie.
Por lo tanto, una implementación que no exponga ninguna información al cliente puede parecer ...
// Storage:
setcookie(
'rememberme',
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce),
time() + 8640000 // 100 days, for example
);
// Validation:
$valid = hash_equals(
$_COOKIE['rememberme'],
hash_hmac('sha256', $username . $_SERVER['REMOTE_ADDR'], $storedNonce)
);
La limitación obvia aquí es que, si su dirección IP (u otra información) cambia, su cookie no sirve para nada. Algunos pueden ver esto como algo bueno, lo veo como innecesariamente hostil hacia la facilidad de uso para los usuarios de Tor.
Ciertamente, puede interpretar que la cita anterior significa algo diferente, como el token JSON Web de un hombre pobre, también. Sin embargo, las cookies HTTP están limitadas a 4 KiB por dominio. El espacio es escaso.
Otro problema: ¿Cuánta información filtra su base de datos sobre su aplicación? (Sí, estoy hablando de canales laterales).
Estrategia segura "Recordarme" de Paragon Initiative
Almacenamiento:
- Genere una cadena de 9 bytes al azar desde
random_bytes()
(PHP 7.0+ o mediante random_compat ), la base64 lo codifica a 12. Esto se utilizará para búsquedas en bases de datos.
- Genere otra cadena aleatoria, preferiblemente de al menos 18 bytes de longitud, y una vez más, codifique en base64 (a 24+). Esto se utilizará realmente para la autenticación.
- Almacene
$lookup
y hash('sha256, $validator)
en la base de datos; por supuesto asociado con una cuenta de usuario específica.
- Almacene
$lookup . $validator
en la cookie HTTP del usuario (por ejemplo, rememberme
).
Validación (Inicio de sesión automático):
- Divida la cookie en
$lookup
y $validator
.
- Realizar una búsqueda en la base de datos basada en
$lookup
; está bien si hay un canal lateral de sincronización aquí.
- Marque
hash_equals($row['hashedValdator'], hash('sha256', $validator))
.
- Si el paso 3 devuelve
TRUE
, asocie la sesión actual con la cuenta de usuario adecuada.
Análisis de seguridad:
-
¿Qué canales laterales se mitigan?
Lo más significativo es que mitiga el impacto de la sincronización de las fugas de información en la operación de comparación de cadenas utilizada en la búsqueda de la base de datos.
Si implementó una autenticación de token aleatoria ingenua, un atacante podría enviar muchas solicitudes hasta que encuentren un token de autenticación válido para un usuario. (Probablemente no podrían seleccionar a qué víctima se están haciendo pasar por la personificación).
-
¿Qué sucede si un atacante puede filtrar la tabla de la base de datos de autenticación a largo plazo?
Almacenamos un hash SHA256 del $validator
en la base de datos, pero el texto plano para el hash se almacena en la cookie. Dado que la entrada es un alto valor de entropía, es poco probable que la búsqueda de fuerza bruta produzca resultados. (Esto también mitiga la necesidad de, por ejemplo, bcrypt.)
Esta estrategia se implementa en Gatekeeper .