En la seguridad de las redes informáticas, los ataques de fijación de sesión intentan explotar la vulnerabilidad de un sistema que permite a una persona fijar (encontrar o configurar) el identificador de sesión de otra persona . La mayoría de los ataques de fijación de sesión se basan en la web y la mayoría se basa en la aceptación de identificadores de sesión de URL ( cadena de consulta ) o datos POST.
Alice tiene una cuenta en el banco.http://unsafe.example.com/
Mallory tiene la intención de apuntar al dinero de Alice de su banco.
Alice tiene un nivel razonable de confianza en Mallory y visitará los enlaces que Mallory le envía.
Escenario sencillo:
http://unsafe.example.com/
acepta cualquier identificador de sesión, acepta identificadores de sesión de cadenas de consulta y no tiene validación de seguridad. http://unsafe.example.com/
por lo tanto no es seguro.http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID
". Mallory está intentando fijar el SID en I_WILL_KNOW_THE_SID
.http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID
. Aparece la pantalla de inicio de sesión habitual y Alice inicia sesión.http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID
y ahora tiene acceso ilimitado a la cuenta de Alice.Una idea errónea es que si un servidor sólo acepta identificadores de sesión generados por el servidor, está a salvo de ser reparado. Esto es falso .
Guión:
http://vulnerable.example.com/
y comprueba qué SID se devuelve. Por ejemplo, el servidor puede responder: Set-Cookie: SID=0D6441FEA4496C2
.http://vulnerable.example.com/?SID=0D6441FEA4496C2
".SID=0D6441FEA4496C2
.http://vulnerable.example.com/?SID=0D6441FEA4496C2
y ahora tiene acceso ilimitado a la cuenta de Alice.Este tipo de ataque es similar a un ataque de cookies entre sitios, excepto que no depende de la vulnerabilidad del navegador del usuario. Más bien, se basa en el hecho de que un subdominio puede configurar cookies comodín y que esas cookies pueden afectar a otros subdominios.
Guión:
www.example.com
entrega subdominios a terceros que no son de confianzaevil.example.com
, atrae a Alice a su sitio.evil.example.com
establece una cookie de sesión con el dominio .example.com
en el navegador de Alice.www.example.com
esta cookie se enviará con la solicitud y Alice tendrá la sesión especificada por la cookie de Mallory.Cuando se complete este ataque, Mallory podrá acceder www.example.com
como Alice.
No es esencial que un usuario inicie sesión para aprovechar los ataques de fijación de sesión [1] y, aunque estos ataques no autenticados no se limitan a ataques de cookies entre subdominios, las implicaciones de los ataques de subdominios son relevantes para estos escenarios no autenticados. Por ejemplo, Mallory puede proporcionar una URL de su sitio malvado, fijar una sesión en un escenario no autenticado y utilizar esas técnicas para explotar su objetivo. Esto incluye escenarios que explotan tanto los escenarios no autenticados (por ejemplo, formularios o registro) como la capacidad de alimentar al usuario con una sesión establecida para evitar el inicio de sesión por completo.
Considere, por ejemplo, que Mallory puede crear un usuario A1ice en www.example.com e iniciar sesión en ese usuario para capturar un identificador de sesión válido y actual. Luego, Mallory atrapa a Alice con una URL de evil.example.com que fija esa cookie de sesión en el navegador de Alice (como se describe arriba) y redirige a www.example.com para finalizar una transacción particular (o, de hecho, un uso más amplio). De este modo, Mallory puede eliminar la sesión de su inicio de sesión original, extrayendo datos y ejecutando operaciones como 'A1ice' en 'www.example.com'. Si Alice fue engañada con éxito y guardó su tarjeta de crédito en la cuenta, Mallory podría realizar compras con esa tarjeta.
No se recomiendan los identificadores de sesión en URL (cadena de consulta, variables GET) o variables POST, ya que simplifican este ataque: es fácil crear enlaces o formularios que establezcan variables GET/POST.
Nota: Las cookies se comparten entre pestañas y ventanas emergentes del navegador. Si su sistema requiere ser utilizado con el mismo dominio (www.example.com/?code=site1 y www.example.com/?code=site2), las cookies pueden entrar en conflicto entre sí entre pestañas.
Es posible que sea necesario enviar el identificador de sesión en la URL para superar esta limitación. Si es posible, utilice site1.example.com o site2.example.com para que no haya conflictos de dominio en las cookies. Esto puede generar costos con certificados SSL adicionales.
Este comportamiento se puede ver en muchos sitios al abrir otra pestaña e intentar hacer resultados de búsqueda uno al lado del otro. Una de las sesiones quedará inutilizable.
Este ataque se puede evitar en gran medida cambiando el ID de sesión cuando los usuarios inician sesión. Si cada solicitud específica de un usuario requiere que el usuario se autentique ("inicie sesión") en el sitio, un atacante necesitaría conocer el ID de la víctima. sesión de inicio de sesión. Sin embargo, cuando la víctima visita el enlace con la identificación de sesión fija, deberá iniciar sesión en su cuenta para poder hacer algo "importante" por sí misma. En este punto, su ID de sesión cambiará y el atacante no podrá hacer nada "importante" con el ID de sesión anónimo.
Se puede utilizar una técnica similar para resolver el problema del phishing . Si el usuario protege su cuenta con dos contraseñas, entonces el problema se puede solucionar en gran medida.
Esta técnica también es útil contra ataques de falsificación de solicitudes entre sitios .
El identificador de sesión en la mayoría de los sistemas modernos se almacena de forma predeterminada en una cookie HTTP , que tiene un nivel moderado de seguridad siempre que el sistema de sesión ignore los valores GET/POST. [ cita necesaria ] Sin embargo, esta solución es vulnerable a la falsificación de solicitudes entre sitios y no cumple con el requisito de apatridia de REST .
Al habilitar la seguridad HTTPS , algunos sistemas permiten que las aplicaciones obtengan el identificador de sesión SSL/TLS . El uso del identificador de sesión SSL/TLS es muy seguro, pero muchos lenguajes de desarrollo web no proporcionan una funcionalidad integrada sólida para esto.
Una contramedida contra la fijación de sesiones es generar un nuevo identificador de sesión (SID) en cada solicitud. Si se hace esto, aunque un atacante pueda engañar a un usuario para que acepte un SID conocido, el SID no será válido cuando el atacante intente reutilizarlo. La implementación de dicho sistema es simple, como lo demuestra lo siguiente:
OLD_SID
de la solicitud HTTP.OLD_SID
es nulo, está vacío o no OLD_SID
existe ninguna sesión con SID=, cree una nueva sesión.NEW_SID
con un generador de números aleatorios seguro.NEW_SID
(y ya no por SID= OLD_SID
)Ejemplo:
Si Mallory logra engañar a Alice para que la visite http://victim.example.com/?SID=I_KNOW_THE_SID
, esta solicitud HTTP se envía a victim.example.com
:
GET /?SID=I_KNOW_THE_SID HTTP / 1.1 Host : víctima.ejemplo.com
victim.example.com
acepta SID=I_KNOW_THE_SID
, lo que normalmente sería malo. Sin embargo, victim.example.com
es seguro porque realiza la regeneración de sesión. victim.example.com
obtiene la siguiente respuesta:
HTTP / 1.1 200 OK Establecer cookies : SID=3134998145AB331F
Alice ahora usará SID=3134998145AB331F
algo que Mallory desconoce y SID=I_KNOW_THE_SID
no es válido. Por tanto, Mallory no tiene éxito en el intento de fijar la sesión.
Lamentablemente, la regeneración de la sesión no siempre es posible. Se sabe que ocurren problemas cuando se utiliza software de terceros, como ActiveX o subprogramas Java, y cuando los complementos del navegador se comunican con el servidor. El software de terceros podría provocar cierres de sesión o la sesión podría dividirse en dos sesiones separadas.
Si la implementación de sesiones incluye la transmisión del SID a través de variables GET o POST, esto también podría inutilizar el botón "atrás" en la mayoría de los navegadores, ya que el usuario estaría usando un identificador de sesión anterior e inválido de una solicitud anterior.
Una forma de mejorar la seguridad es no aceptar identificadores de sesión que no hayan sido generados por el servidor. Sin embargo, como se señaló anteriormente, esto no evita todos los ataques de fijación de sesiones.
if ( ! isset ( $_SESSION [ 'SERVER_GENERATED_SID' ])) { session_destroy (); // Destruye todos los datos de la sesión } session_regenerate_id (); // Genera un nuevo identificador de sesión $_SESSION [ 'SERVER_GENERATED_SID' ] = true ;
Una función de cierre de sesión es útil ya que permite a los usuarios indicar que una sesión no debe permitir más solicitudes. Por tanto, los ataques sólo pueden ser efectivos mientras una sesión está activa. Tenga en cuenta que el siguiente código no realiza comprobaciones de falsificación de solicitudes entre sitios , lo que podría permitir que un atacante obligue a los usuarios a cerrar sesión en la aplicación web.
if ( cerrar sesión ) { session_destroy (); // Destruye todos los datos de la sesión }
Esta defensa es sencilla de implementar y tiene la ventaja de proporcionar una medida de protección contra el acceso de usuarios no autorizados a la cuenta de un usuario autorizado mediante el uso de una máquina que puede haber quedado desatendida.
Almacene una variable de sesión que contenga una marca de tiempo del último acceso realizado por ese SID. Cuando ese SID se vuelva a utilizar, compare la marca de tiempo actual con la almacenada en la sesión. Si la diferencia es mayor que un número predefinido, digamos 5 minutos, destruya la sesión. De lo contrario, actualice la variable de sesión con la marca de tiempo actual.
Al visitar una página, la mayoría de los navegadores web configurarán el encabezado Referrer : la página que contenía el enlace que siguió para llegar a esta página.
Cuando el usuario inicia sesión en un sitio al que probablemente no se vinculará desde fuera de ese sitio (por ejemplo, sitios web bancarios o correo web ), y el sitio no es el tipo de sitio en el que los usuarios permanecerían conectados durante un período prolongado. momento, el Referente debe ser de ese sitio. Cualquier otro Referente debe ser considerado sospechoso. Sin embargo, si la solicitud de origen proviene de una página HTTPS, entonces se eliminará la referencia, por lo que no puede depender de este sistema de seguridad.
Por ejemplo, http://vulnerable.example.com/
podría emplear el siguiente control de seguridad:
if ( strpos ( $_SERVER [ 'HTTP_REFERER' ], 'http://vulnerable.example.com/' ) !== 0 ) { session_destroy (); // Destruye todos los datos de la sesión } session_regenerate_id (); // Genera un nuevo identificador de sesión
Una forma de mejorar aún más la seguridad es garantizar que el usuario parezca ser el mismo usuario final (cliente). Esto hace que sea un poco más difícil realizar la fijación de sesiones y otros ataques.
A medida que más y más redes comienzan a cumplir con RFC 3704 y otras prácticas contra la suplantación de identidad , la dirección IP se vuelve más confiable como identificador de "la misma fuente". Por lo tanto, la seguridad de un sitio web se puede mejorar verificando que la dirección IP de origen sea coherente durante toda la sesión.
Esto podría realizarse de esta manera:
if ( $_SERVER [ 'REMOTE_ADDR' ] != $_SESSION [ 'PREV_REMOTEADDR' ]) { session_destroy (); // Destruye todos los datos de la sesión } session_regenerate_id (); // Genera un nuevo identificador de sesión $_SESSION [ 'PREV_REMOTEADDR' ] = $_SERVER [ 'REMOTE_ADDR' ];
Sin embargo, hay algunos puntos a considerar antes de emplear este enfoque.
Para algunos sitios, la seguridad adicional supera la falta de comodidad, y para otros no.
Los navegadores se identifican mediante encabezados HTTP "User-Agent". Este encabezado normalmente no cambia durante el uso; Sería extremadamente sospechoso si eso sucediera. Una aplicación web puede utilizar la detección de agente de usuario para intentar evitar que usuarios malintencionados roben sesiones. Sin embargo, esto es trivial de evitar, ya que un atacante puede capturar fácilmente el agente de usuario de la víctima con su propio sitio y luego falsificarlo durante el ataque. Este sistema de seguridad propuesto se basa en la seguridad a través de la oscuridad .
if ( $_SERVER [ 'HTTP_USER_AGENT' ] != $_SESSION [ 'PREV_USERAGENT' ]) { session_destroy (); // Destruye todos los datos de la sesión } session_regenerate_id (); // Genera un nuevo identificador de sesión $_SESSION [ 'PREV_USERAGENT' ] = $_SERVER [ 'HTTP_USER_AGENT' ];
Sin embargo, hay algunos puntos a considerar antes de emplear este enfoque.
Pero el Agente de Usuario puede cambiar legalmente en algunos casos. Los siguientes ejemplos son los mismos usuarios.
Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 Build/VZW) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 854X480 motorola DROID2
Mozilla/5.0 (Linux; U; Android 2.2; en-us; DROID2 Build/VZW) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 480X854 motorola DROID2
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/0.0.5; +http://flipboard.com/browserproxy)
Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6 (FlipboardProxy/1.1; +http://flipboard.com/browserproxy)
La defensa en profundidad consiste en combinar varias contramedidas. La idea es simple: si un obstáculo es trivial de superar, varios obstáculos podrían ser muy difíciles de superar.
Una estrategia de defensa en profundidad podría implicar:
Las referencias HTTP no se pasan con SSL/TLS (HTTPS).
El siguiente script PHP demuestra varias de estas contramedidas combinadas en una forma de defensa en profundidad:
if ( isset ( $_GET [ 'LOGOUT' ]) || $_SERVER [ 'REMOTE_ADDR' ] !== $_SESSION [ 'PREV_REMOTEADDR' ] || $_SERVER [ 'HTTP_USER_AGENT' ] !== $_SESSION [ 'PREV_USERAGENT' ] ) { sesión_destroy (); }session_regenerate_id (); // Genera un nuevo identificador de sesión$_SESSION [ 'PREV_USERAGENT' ] = $_SERVER [ 'HTTP_USER_AGENT' ]; $_SESSION [ 'PREV_REMOTEADDR' ] = $_SERVER [ 'REMOTE_ADDR' ];
Tenga en cuenta que este código verifica el REMOTE_ADDR (la dirección IP del usuario) y el User-agent actuales con el REMOTE_ADDR y el User-agent de la solicitud anterior. Esto puede resultar inconveniente para algunos sitios, como se analizó anteriormente.