Si hacemos una simple consulta en Google, “variables de sesión seguras” o “sesiones seguras en php”, veremos que en la mayoría de foros aseguran que son totalmente seguras. ¿Pero realmente lo son? En realidad no y existen tres tipos de ataques para comprometer la seguridad de las variables de sesión:

  • Prediction
  • Capture
  • Fixation

El método prediction consiste en adivinar un identificador de sesión válido, es el ataque menos común pues PHP provee de identificadores de sesión aleatorios.

El método capture consiste en capturar una variable de sesión. Es uno de los métodos más comunes debido a que su funcionamiento se basa en el mecanismo de propagación de las sesiones: utilizando cookies o utilizando el método GET. Se aprovecha de las vulnerabilidades encontradas en los navegadores para capturar cookies o capturar variables GET. Las variables propagadas mediante cookies son más seguras que las propagadas mediante el método GET en tanto que las primeras es necesario acceder a la máquina física del perjudicado para poder robar la cookie.

El tercer y último método, fixation, consiste en obtener un identificador de sesión válido. Es el más fácil de atacar y el más fácil de proteger.

Nociones básicas

El protocolo HTTP es un protocolo sin estado, es decir que no dispone de un método que permita conservar el estado entre dos transacciones. Cuando solicitamos una página y después otra, HTTP no cuenta con ninguna técnica para que podamos saber que ambas solicitudes provienen del mismo usuario. De aquí surge el concepto de control de sesiones que consiste en realizar el seguimiento de un usuario durante una sola sesión en un sitio Web.

En PHP, las sesiones se controlan por un solo Id. de sesión, un número criptográficamente aleatorio, generador por el motor de PHP y que se almacena en el lado del cliente mientras dura la sesión. Se puede almacenar de dos maneras: en forma de cookie o pasarse por  medio de URL.

Este identificador actúa como clave para poder registrar determinadas variables de sesión. Las variables de sesión y sus contenidos se almacenan en el servidor.

Ejemplo de ataque “fixation”

Creamos el siguiente script, sesion.php:

<?php

session_start();

if (!isset($_SESSION['visitas']))
{
    $_SESSION['visitas'] = 1;
}
else
{
    $_SESSION['visitas']++;
}

echo $_SESSION['visitas'];

?>

La primera vez que visitemos el script sesion.php (es decir, que no hemos creado ninguna sesión con este script con anterioridad) se creará una variable llamada $_SESSION[‘visitas’] que actuará como contador de visitas y se inicializará con el valor entero 1. En visitas posteriores este contador se irá incrementando, hasta que la sesión caduque o la destruyamos. Ahora dile a un amigo (o si tienes el script en un servidor local prueba abriendo dos navegadores distintos, imaginándote que uno es tu navegador y el otro es el navegador de un juacker muy malo) que ejecute el script de la siguiente manera: http://tudominio.com/sesion.php?PHPSESSID=1234. Tu amigo habrá creado la variable contador descrita anteriormente y habrá sido inicializada con el valor 1, hasta aquí todo bien. Ahora tú visita la misma URL <<http://tudominio.com/sesion.php?PHPSESSID=1234 y recuerda que es la primera vez que visitas la página, así que el contador $_SESSION[‘visitas’] para ti también debería valer 1. Pero no es así, el contador tendrá un valor superior pues al pasar por el método GET la variable PHPSESIDD con el valor 1234  lo que estás haciendo es utilizar las mismas variables de sesión -y sus valores- que creó tu amigo en un principio con Id. 1234. Recuerda que las variables de sesión se almacenan en el servidor web y no en tu máquina, por eso habéis compartido las mismas variables al haber utilizado el mismo identificador de sesión.

Cualquier atacante malicioso podría crear variables de sesión en tu ordenador ocultando y ejecutando peticiones HTTP en fotos enviadas por email, por ejemplo.

La solución es fácil. Sólo debemos regenerar el identificador de sesión cada vez que un usuario crea una sesión por primera vez:

<? Php

 session_start ();

 if (! isset ($ _SESSION ['iniciado']))
 {
     session_regenerate_id ();
     $ _SESSION ['Iniciado'] = true;
 }

 ?>

Otra manera de evitar este ataque es decirle a PHP que sólo permita acceder al identificador de sesión mediante cookies. Para ello deberemos cambiar la directiva session.use_only_cookies del php.ini y ponerla a 1. Este ajuste fue introducido en la versión 4.3.0 de PHP y desde la versión 5.3.0 su valor por defecto es 1(habilitado).

Y aún almacenando los Id. de sesión solamente en cookies no estamos seguros del todo, alguien podría acceder a nuestro ordenador y robar esa cookie. En un artículo posterior explicaremos cómo almacenar las Id. de sesión en una base de datos como sustitución y mejora del mecanimo dual URL/Cookie que ofrece PHP por defecto.