Hola, somos Arume

Desarrollamos páginas web, aplicaciones para móviles, capas de realidad aumentada y aplicaciones para Facebook. Nos apasiona la informática y somos unos perfeccionistas incurables; por eso en nuestros proyectos utilizamos estándares.

tel. 625 519 694

Mendaña de Neyra, 34, 3º B, 15008, A Coruña

Autenticarse

Registrarse. ¿Has olvidado tu contraseña?

Etiquetas

Saltar las etiquetas

Suscríbete a las RSS

Estás en:

  • Inicio >
  • Blog >
  • Seguridad de las sesiones en PHP: Session Fixation

Seguridad de las sesiones en PHP: Session Fixation

23 Dic 2010 por Luis

Comentarios: 5

Fijación de sesión

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.

Cómo se realiza el ataque

Como podemos leer en el artículo sobre el funcionamiento de las sesiones, hay varias 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:

http://www.web-atacada.com/?PHPSESSID=123456

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.

Atención: 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í:

    ini_set('session.use_only_cookies', 1);
  • 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:

    session_start();
    
    if (isset($_SESSION['mark']) === false)
    {
    	session_regenerate_id(true);
    	$_SESSION['mark'] = true;
    }
  • 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:

    if ($user_logged_in === true)
    {
    	session_regenerate_id(true);
    	$_SESSION['logged'] = true;
    }

Aviso: 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.

En el próximo y definitivo artículo sobre vulnerabilidades de las sesiones, un último tipo de ataque y su prevención.

Comentarios

5 comentarios. Comentar.

1. Eldev el 08 Mar 2011 a las 05:06:00

muy bueno y util su aporte, sigan asi :).

Consejo: Aumenten el tamaño de las letras del texto y que el color del mismo contraste mas con el fondo ;)

2. Pedro el 14 Abr 2011 a las 07:04:50

muchas gracias por el pequeño tutorial es de mucha utilidad

3. Josue Sanchez el 12 Feb 2016 a las 16:23:25

Hola,

Una duda que me genera al ver este buen tutorial es... como debo cerrar después la session?

4. Caimán el 28 Sep 2016 a las 22:20:19

Buenas, quiero felicitarte por la claridad de las explicaciones en general.

Tengo una duda con respecto a la regeneración del id de sesión.

Si el server tiene los siguientes registros:

Cliente A con PHPSESSID = 12345

Cliente B con PHPSESSID = 78945

Cada vez que el cliente A realice una acción, a este se le regenerará el PHPSESSID. Supongamos que este realizó una acción y se le regeneró su PHPSESSID a "55555".

Si el Cliente B utiliza el PHPSESSID = 55555, entonces ingresaría como el Cliente A y se le regeneraría su PHPSESSID nuevamente y no serviría de nada... Como funciona esto?

5. Luis el 30 Sep 2016 a las 12:02:24

Hola Caimán.

El servidor se encarga de que no se genere un PHPSESSID que ya está siendo usado.

De todas formas, aunque yo he puesto aquí identificadores como los que tú indicas, lo he hecho sólo para que se entendiese la explicación. En realidad, los PHPSESSID son (por defecto) así: 31d7bgphebfemb55311b1cger6. La probabilidad de que se repita un identificador de sesión es muy baja (si fuese fácil que se repitiesen, sería muy fácil atacar un sistema utilizando identificadores de sesión al azar).

Un saludo.

Comentar

Comentar de forma anónima

Puedes comentar poniendo cualquier nombre o apodo, exceptuando los nombres de usuarios registrados. Máximo de 50 caracteres.

Comentar como usuario registrado

Registrarse. ¿Has olvidado tu contraseña?