php - son - Codificación de cookies para que no puedan ser falsificadas o leídas, etc.
que son los cookies de una pagina web (5)
Estoy escribiendo una aplicación PHP. Quiero almacenar la información de inicio de sesión del usuario en las cookies para que el usuario no tenga que iniciar sesión en cada visita.
Quiero codificarlos u ofuscarlos para que no puedan ser leídos o manipulados.
¿Cuál es la mejor manera de hacer esto?
Actualizar:
No voy a almacenar contraseñas en las cookies, simplemente un ID de usuario para saber quiénes son, pero quiero que esto esté codificado o encriptado para que nadie pueda falsificar a otros usuarios.
La respuesta corta
No lo hagas Lo lamentarás a largo plazo. Claro, usted podría cifrarlo, pero qué sucede cuando alguien descubre su clave de cifrado. Ahora simplemente les entregó las credenciales de todos en un plato (bueno, no realmente, pero lo suficientemente cerca).
Una mejor manera de hacerlo
En lugar de almacenar el nombre de usuario y la contraseña cifrados, ¿por qué no crear un token aleatorio y almacenarlo con el nombre de usuario? Usted querría algo considerable, por lo que algo como un hachís sha256
debería ser suficiente.
$randomToken = hash(''sha256'',uniq_id(mt_rand(), true).uniq_id(mt_rand(), true));
Luego, guárdelo en la base de datos junto con el usuario y envíe una cookie al cliente (también sugeriría que también firme el token para evitar la manipulación):
$randomToken .= '':''.hash_hmac(''md5'', $randomToken, $serverKey);
Ahora, cuando verifique, primero verifique que el hash coincida:
list($token, $hmac) = explode('':'', $_COOKIE[''remember_me''], 2);
if ($hmac != hash_hmac(''md5'', $token, $serverKey)) {
die(''tampered token!'');
}
A partir de ahí, solo busca al usuario por el token. Si encuentra uno, inicie sesión en ese usuario.
También sugiero cambiar el token en cada cambio de contraseña.
Para responder a su pregunta directamente
Nota: no hagas esto en vivo, código de producción . Nunca puedes confiar completamente en los datos que salen de tu servidor web. Así que no expongas la información de tu usuario de esa manera. Que no vale la pena. Sin embargo, agregué algunos controles adicionales (como firmar la cookie) para hacerlo un poco más seguro, pero se le advirtió ...
Para codificarlo, usaría mcrypt
para cifrar los datos en la cookie. Luego, haría un salt al azar y lo almacenaría con la fila del usuario, y luego firmaría los datos cifrados con hash_hmac
usando ese salt único. De esa manera, si alguien intercepta la cookie y descubre la clave para la cripta, aún puede detectar el hmac no válido, por lo que puede encontrar sabotajes.
function generateCredentialsCookie($user_id, $password) {
$encrypted = encrypt($user_id.'':''.$password, $secretkey);
$salt = uniq_id(mt_rand(), true);
$encrypted .= '':''.hash_hmac(''sha256'', $encrypted, $salt);
storeSaltForUser($user_id, $salt);
set_cookie(''credentials'', $encrypted);
}
function readCredentialsCookie() {
$parts = explode('':'', $_COOKIE[''credentials'']);
$salt = array_pop($parts);
$encrypted = implode('':'', $parts); //needed incase mcrypt added `:`
$raw = decrypt($encrypted, $secretkey);
list ($user_id, $password) = explode('':'', $raw, 2);
if ($salt == getSaltForUser($user_id))
return array($user_id, $password);
} else {
return die(''Invalid Cookie Found'');
}
}
Nota - eso es pseudo-código. Necesitará mucho más para estar seguro (como verificar valores no válidos, asegurarse de que se descifre correctamente, etc.).
¡NO use sesiones de larga duración!
Debe mantener la caducidad de la sesión tan baja como sea práctico (normalmente uso sesiones de 30 minutos, pero algunos sitios son más bajos). El tiempo de caducidad es posterior al último uso, por lo que siempre que el sitio se use de forma activa no importará.
En cuanto a por qué no usar una sesión de larga duración, aquí hay algunas desventajas:
DOS ( se crean vulnerabilidades de denegación de servicio )
Espacio en disco: cada sesión utiliza una cantidad razonablemente pequeña de espacio en disco. Pero cuando tiene una sesión de larga duración, cada sesión nueva solo se suma al total anterior. Entonces, con las sesiones de larga duración, alguien solo necesita seguir visitando su sitio una y otra vez con un nuevo ID de sesión y, de repente, se queda sin espacio en el disco (suponiendo que sea un disco sano).
Espacio de carpeta: cada sesión toma un archivo en una carpeta. Los sistemas de archivos más populares se ralentizarán con una gran cantidad de archivos en una sola carpeta. Entonces, si coloca 1 millón de archivos de sesión, leer o escribir en un archivo de sesión será lento (muy lento). Y la recolección de basura (que limpia archivos antiguos) será MUY MUY MUY lenta (si es que se ejecuta).
Se abren las vulnerabilidades de secuestro de sesión . Esto se debe a que cuantas más sesiones tengas abiertas en el sitio, más fácil será adivinar un identificador válido (gracias al ataque de cumpleaños ). Cuantas menos sesiones tengas, más difícil será adivinar una válida.
Probablemente hay otros, pero eso es un resumen rápido. En lugar de sesiones de larga duración, use un token recordarme firmado como se describe anteriormente. Estarás mucho mejor y mucho más seguro ...
Absolutamente, en ningún caso debe almacenar las credenciales de los usuarios en la cookie. Siempre debe asumir que las cookies, como todos los comentarios del usuario, no pueden ser confiables.
Un par de métodos:
Si el usuario elige "recordarme", simplemente configure lo siguiente antes de inicializar su sesión.
session_set_cookie_params(60 * 60 * 24 * 7); //save cookie session for 7 days
De lo contrario, almacene un token único en la base de datos, y consulte ese token para ver si pertenece a un usuario y, si es así, complete su sesión.
Aunque recomendaría la primera opción.
Almacenar los datos del usuario en una cookie es la manera incorrecta. Deberías usar las sesiones de PHP . Lo único que se almacenará en el cliente será el ID de sesión en una cookie simple (que PHP manejará por usted automáticamente). Ya es una cadena encriptada.
PHP hará un seguimiento de los datos del usuario en el lado del servidor.
Esto logrará el efecto deseado que ha descrito, mientras se mantiene más seguro que el uso de cookies.
Es más sencillo generar un número aleatorio seguro criptográficamente de 16 o más y almacenar esto en la cookie. No hay necesidad de cifrar / descifrar. Úselo con un tiempo de validez limitado verificado en el lado del servidor (no confíe en MaxAge o Expires). Esta es una cookie de sesión.
Esto es muy seguro ya que ninguna información crítica abandona el servidor.
La desventaja de esta técnica es que necesita crear un índice de base de datos para esa ID de sesión y hacer una búsqueda en la base de datos para cada solicitud. Eso podría ser lo suficientemente bueno para la mayoría de los sitios web siempre que la latencia no sea perceptible y el servidor se acepte.
Para minimizar la carga del servidor y la latencia de respuesta, el almacenamiento de la ID de usuario, su función y el sello de creación de cookie dentro de un valor de cookie seguro es una opción válida. No se requieren datos de la base de datos o caché para eliminar las solicitudes no válidas y, si la identificación del usuario es compacta, el índice será pequeño y más rápido de búsqueda. Pero no invente su propia codificación de valor seguro a menos que sepa lo que está haciendo.
La desventaja de este método es que si alguien descubre la clave, puede falsificar cookies. Luego puede crear cookies con diferentes identificadores de usuario y acceder a su cuenta. Entonces, use este método donde el riesgo es limitado y el acceso a la clave está bien controlado. Un dispositivo de hardware dedicado que realice el cifrado / descifrado y que oculte la clave podría ser una solución. Pero eso es actualmente poco común y costoso. Es posible que la latencia sea más grande que buscar un ID de sesión aleatorio en un caché. La última es la solución más sencilla y segura.
El uso de claves públicas / privadas para asegurar el valor en la cookie, podría usarse para asegurar la clave privada. Pero es mucho más complejo hacerlo bien, y la latencia podría ser comparable a un sistema con un simple ID de sesión en caché aleatorio.
Tenga en cuenta también que cualquier método que utilice cookies requiere el uso de HTTPS. De lo contrario, un hombre en el medio o alguien que espía los datos intercambiados podría obtener fácilmente una copia de la cookie y hacerse pasar por el usuario.
Galleta de sal antes de guardar. Agregue user-agent, ip como desee ampliar la seguridad.
$cookie_to_save = sha1($pwd . $user_agent . $yourSalt);
en autologin
if($cookie_saved == sha1($pwd . $user_agent . $yourSalt) ok...