Session fixation (fijación de sesión) es un método de Session hijacking (robo de sesión) un poco especial, ya que, si normalmente en el robo de sesión se intenta conseguir el identificador de sesión de un usuario ya autenticado, la fijación de sesión se basa en asignar un identificador de sesión conocido a un usuario antes de que se autentique.
Por hacer una analogía: el robo de sesión es como intentar robar la clave de una tarjeta de crédito, mientras que la fijación de sesión es intentar que la víctima cambie su clave a un número dado (y por lo tanto conocido) por el atacante.
Lo malo de este ataque es que es muy fácil de realizar. Lo bueno, es que es muy fácil de prevenir.
Existen distintas formas de propagarlas entre páginas de un mismo sitio web. Una de ellas, la URL, es la más fácil de atacar, supongamos que la página web atacada utiliza el nombre de sesión por defecto en PHP: PHPSESSID. El atacante sólo tiene que crear un enlace a la página web objetivo de esta forma: Después, sólo tiene que hacer que el usuario al que quiere atacar utilice ese enlace para acceder a la página web. Esto se puede conseguir de varias formas: enviándole el enlace por email, a través de una red social o, incluso, sin que el usuario se dé cuenta, haciendo una redirección desde una página web del atacante.
Una vez que el usuario utiliza este enlace, le está diciendo a la página web que su identificador de sesión es 123456. PHP al comprobar que no existe una sesión con ese identificador, la crea y se la asigna al usuario. Si este se autentica en el sitio, el atacante, que conoce su identificador de sesión (123456), puede hacerse con su cuenta haciéndose pasar por él.
Si bien es un ataque que se puede realizar fácilmente, la prevención es igualmente fácil. Podemos tomar las siguientes medidas:
Por hacer una analogía: el robo de sesión es como intentar robar la clave de una tarjeta de crédito, mientras que la fijación de sesión es intentar que la víctima cambie su clave a un número dado (y por lo tanto conocido) por el atacante.
Lo malo de este ataque es que es muy fácil de realizar. Lo bueno, es que es muy fácil de prevenir.
Realización del ataque
Existen distintas formas de propagarlas entre páginas de un mismo sitio web. Una de ellas, la URL, es la más fácil de atacar, supongamos que la página web atacada utiliza el nombre de sesión por defecto en PHP: PHPSESSID. El atacante sólo tiene que crear un enlace a la página web objetivo de esta forma: Después, sólo tiene que hacer que el usuario al que quiere atacar utilice ese enlace para acceder a la página web. Esto se puede conseguir de varias formas: enviándole el enlace por email, a través de una red social o, incluso, sin que el usuario se dé cuenta, haciendo una redirección desde una página web del atacante.
Una vez que el usuario utiliza este enlace, le está diciendo a la página web que su identificador de sesión es 123456. PHP al comprobar que no existe una sesión con ese identificador, la crea y se la asigna al usuario. Si este se autentica en el sitio, el atacante, que conoce su identificador de sesión (123456), puede hacerse con su cuenta haciéndose pasar por él.
Nota: aunque la página web utilice cookies para la propagación del identificador de sesión, normalmente la configuración de PHP acepta el identificador en la URL (después lo propaga a través de cookies pero cuando ya ha creado la sesión con ese identificador). También hay que tener en cuenta que un atacante puede (con técnicas mucho más avanzadas y aprovechando errores en las directivas de seguridad de los navegadores) realizar este ataque insertando una cookie al usuario. Aunque es la forma más sencilla, este ataque no se limita sólo a la propagación por URL.
Métodos de Prevención
Si bien es un ataque que se puede realizar fácilmente, la prevención es igualmente fácil. Podemos tomar las siguientes medidas:
- Utilizar únicamente cookies para la propagación del identificador de sesión. Esta medida no anula el peligro, pero hace más difícil el ataque (y muchos otros). En PHP se consigue así:
- Regenerar los identificadores de sesión para sesiones nuevas. Esto se consigue poniendo una "marca" en las sesiones de la página web. Cada vez que se hace un session_start(), si la sesión no tiene la "marca", cambiamos su identificador por uno nuevo (session_regenerate_id(true);) y desconocido para el atacante. Ejemplo:
- Cambiar el identificador de sesión siempre que un usuario cambie su estado (autenticado, registrado, ...). Con la anterior medida de protección puede parecer que ya estamos protegidos, pero un atacante puede entrar en la página web, generar una sesión con "marca" y después mandar el identificador de esa sesión al usuario atacado. Así el usuario atacado acabaría con una sesión con "marca" y conocida por el atacante. Por eso, se debe regenerar el identificar de sesión siempre que un usuario realice una acción que le obligue a autenticarse. Ejemplo:
Nota: es muy importante que sea session_regenerate_id(true); y no session_regenerate_id(); ya que si no eliminamos la sesión antigua, estamos haciendo más fácil los ataques contra la página web al dejar múltiples sesiones válidas abiertas en el servidor.