La fijación de sesión es cuando la víctima inicia sesión con un ID que el atacante preparó. Aquí tienes cómo funciona y cómo prevenirla de forma fiable (sin pasos de ataque).
Por qué funciona
La causa es un diseño donde el ID de sesión no cambia al iniciar sesión. Si no cambia, un ID que el atacante conocía antes del inicio de sesión sigue funcionando como «autenticado» después del inicio de sesión.
Puede combinarse con CSRF o XSS, pero la esencia de la fijación en sí es una sola cosa: el ID no se regeneró al iniciar sesión.
La guía de la IPA de Japón (Information-technology Promotion Agency) «How to Secure Your Website» la trata como una forma de gestión de sesiones inadecuada y advierte que todo sitio web con función de inicio de sesión debe vigilarla. Su corrección de fondo es iniciar una sesión nueva tras un inicio de sesión correcto.
Fijación frente a secuestro de sesión y CSRF
Estos tres se confunden con facilidad. Todos abusan de una sesión iniciada, pero difieren en qué tiene el atacante y qué defensa funciona.
| Aspecto | Fijación de sesión | Secuestro de sesión | CSRF |
|---|---|---|---|
| Qué tiene el atacante | Un ID que preparó él (lo conoce desde el principio) | Un ID ya emitido que ha robado | Ningún ID |
| Qué le pasa a la víctima | Inicia sesión con el ID plantado | Le roban el ID ya emitido | Le hacen enviar una petición que no pretendía |
| Defensa principal | Regenerar el ID al iniciar sesión | HttpOnly/Secure, prevención de XSS, vidas cortas | Tokens CSRF, SameSite |
La fijación es la que un único paso, regenerar el ID al iniciar sesión, corrige de raíz.
Defensa: regenera el ID al iniciar sesión
Regenera el ID de sesión al iniciar sesión con éxito (lo más importante)
No aceptes IDs de sesión por la URL
Configura las marcas de la cookie
HttpOnly (JS no puede leerlas), Secure (solo HTTPS) y SameSite (frena el envío entre sitios). Debilita en conjunto las vías de secuestro relacionadas.Caduca las sesiones con criterio
La OWASP Session Management Cheat Sheet recomienda regenerar el ID en cada cambio de privilegios y usar un mecanismo «estricto» que solo acepte IDs generados por el propio servidor. Un mecanismo «permisivo» que adopta un ID desconocido traído de fuera deja margen para que se acepte un ID elegido por el atacante.
Qué hacen por defecto los frameworks habituales
La mayoría de los frameworks regeneran el ID automáticamente si usas su inicio de sesión estándar. El riesgo aparece cuando escribes tú el inicio de sesión o desactivas la protección predeterminada.
| Entorno | Comportamiento predeterminado | Qué revisar si lo escribes tú |
|---|---|---|
| PHP (sesiones nativas) | No regenera por sí solo; session.use_strict_mode vale 0 por defecto | Llama a session_regenerate_id(true) al iniciar sesión con éxito; pon use_strict_mode a 1 |
| Laravel | Se regenera automáticamente al autenticar si usas un starter kit o Fortify | Si escribes el inicio de sesión a mano, llama a $request->session()->regenerate() |
| Spring Security | Activado por defecto (changeSessionId en Servlet 3.1+) | Asegúrate de que nadie ha configurado sessionFixation().none() |
En PHP, las opciones que pasan los IDs de sesión por la URL (activar session.use_trans_sid, desactivar session.use_only_cookies) quedaron obsoletas en PHP 8.4. Si arrastras un archivo de configuración antiguo, revísalas.
Cómo revisar tu propio sitio
En un sitio que administres, comprueba estas cuatro cosas. Solo necesitas las herramientas de desarrollo.
- En las herramientas de desarrollo, en «Application» (Firefox: «Storage»), anota el valor de la cookie de sesión y vuelve a mirarlo tras iniciar sesión. Si no ha cambiado, el ID no se regenera al iniciar sesión
- Comprueba que ni la página de inicio de sesión ni las URLs posteriores llevan un ID de sesión como
PHPSESSID=o;jsessionid= - En el mismo panel, comprueba que la cookie de sesión tiene
HttpOnly,SecureySameSite - Tras cerrar sesión, vuelve a poner el valor antiguo de la cookie y recarga; confirma que no vuelves a tener la sesión iniciada
Los atributos de las cookies también los revisa la auditoría de seguridad del sitio, que analiza sitios cuya propiedad has verificado. Si conviertes la comprobación 1 en una prueba automática cada vez que tocas el flujo de inicio de sesión, notarás enseguida si la regeneración desaparece.
La visión de este sitio: no desactives el 'regenerate' del framework
La fijación de sesión se previene en gran medida con un solo paso: regenerar el ID al iniciar sesión, no con código personalizado elaborado. La clave es no desactivar por accidente ni olvidarse de llamar al mecanismo que tu framework ya proporciona. Usar los valores predeterminados seguros de una implementación probada supera a montar tu propia gestión de sesiones a mano. En este sitio nos atenemos a «no construyas tú mismo la autenticación/gestión de claves; no desactives los valores predeterminados seguros». Como con el IDOR, la autenticación/autorización debe imponerse mediante un mecanismo en cada solicitud.
Fuentes (primarias)
- IPA, «How to Secure Your Website», 1.4 Gestión de sesiones inadecuada — ipa.go.jp (en japonés; iniciar una sesión nueva tras el inicio de sesión; no poner IDs en la URL)
- OWASP Session Management Cheat Sheet — cheatsheetseries.owasp.org (en inglés; regeneración al cambiar de privilegios, mecanismo estricto, atributos de cookie)
- MITRE CWE-384: Session Fixation — cwe.mitre.org (en inglés)
- Manual de PHP, «Runtime Configuration» (sesiones) — php.net (en inglés; valores predeterminados como
use_strict_mode; obsolescencias de 8.4) - Documentación de Laravel, «HTTP Session» — laravel.com / Spring Security, «Authentication Persistence and Session Management» — docs.spring.io (en inglés)
Sigue leyendo
- Glosario: Qué es CSRF · Qué es XSS · Qué es IDOR · Qué es un JWT
- Fundamentos: Autenticación frente a autorización