En seguridad de 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 establecer) 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 dependen de que los identificadores de sesión se acepten de las URL ( cadena de consulta ) o de los datos POST.
Escenarios de ataque
Alice tiene una cuenta en el banco.http://unsafe.example.com/
Mallory pretende quedarse con el dinero de Alice de su cuenta bancaria.
Alice confía razonablemente en Mallory y visitará los enlaces que ella le envíe.
Un escenario de ataque simple
Escenario sencillo:
- Mallory ha determinado que
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. - Mallory le envía un correo electrónico a Alice: "Oye, mira esto, hay una nueva y genial función de resumen de cuenta en nuestro banco
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID", . Mallory está tratando de fijar el SID aI_WILL_KNOW_THE_SID. - Alice está interesada y visita la página
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SID. Aparece la pantalla de inicio de sesión habitual y Alice inicia sesión. - Mallory la visita
http://unsafe.example.com/?SID=I_WILL_KNOW_THE_SIDy ahora tiene acceso ilimitado a su cuenta.
Ataque mediante SID generado por el servidor
Existe la idea errónea de que si un servidor solo acepta identificadores de sesión generados por el servidor, está a salvo de la fijación. Esto es falso .
Guión:
- Mallory visita
http://vulnerable.example.com/y comprueba qué SID se devuelve. Por ejemplo, el servidor puede responder:Set-Cookie: SID=0D6441FEA4496C2. - Mallory ahora puede enviarle un correo electrónico a Alice: "Mira esta nueva y genial función de nuestro banco,
http://vulnerable.example.com/?SID=0D6441FEA4496C2." - Alice inicia sesión con un identificador de sesión fijo
SID=0D6441FEA4496C2. - Mallory la visita
http://vulnerable.example.com/?SID=0D6441FEA4496C2y ahora tiene acceso ilimitado a su cuenta.
Ataques mediante cookies entre subdominios
Este tipo de ataque es similar a un ataque de cookies entre sitios, con la diferencia de que no se basa en la vulnerabilidad del navegador del usuario. En cambio, se basa en el hecho de que un subdominio puede establecer cookies comodín y que estas pueden afectar a otros subdominios.
Guión:
- Un sitio web
www.example.comdistribuye subdominios a terceros no confiables. - Una de esas partes, Mallory, que ahora controla
evil.example.com, atrae a Alice a su sitio - Una visita a
evil.example.comestablece una cookie de sesión con el dominio.example.comen el navegador de Alice. - Cuando Alice visite la
www.example.compágina, esta cookie se enviará con la solicitud y Alice tendrá la sesión especificada por la cookie de Mallory. - Si Alice inicia sesión ahora, Mallory podrá usar su cuenta.
Cuando este ataque se complete, Mallory podrá acceder www.example.comcomo Alice.
No es esencial que un usuario inicie sesión para explotar 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 a subdominios son relevantes para estos escenarios no autenticados. Por ejemplo, Mallory puede proporcionar una URL de su sitio malicioso, fijando 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 proporcionar al usuario una sesión establecida para eludir completamente el inicio de sesión.
Consideremos, por ejemplo, que Mallory podría crear un usuario llamado A1ice en www.example.com e iniciar sesión con él para capturar un identificador de sesión válido. A continuación, Mallory engaña a Alice con una URL de evil.example.com que fija la cookie de sesión en el navegador de Alice (como se describió anteriormente) y la redirige a www.example.com para finalizar una transacción específica (o, de hecho, para un uso más general). De esta forma, Mallory puede suplantar la sesión original, extraer datos y ejecutar 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 ella.
Contramedidas
No acepte identificadores de sesión de variables GET/POST.
No se recomienda el uso de identificadores de sesión en la URL (cadena de consulta, variables GET) o en las variables POST, ya que simplifican este ataque : es fácil crear enlaces o formularios que establezcan variables GET/POST.
- El SID se filtra a otras personas cuando los usuarios copian y pegan "enlaces interesantes" de la barra de direcciones en chats, foros, comunidades, etc.
- El SID se almacena en muchos lugares (registro del historial del navegador, registro del servidor web , registros del proxy, ...).
Nota: Las cookies se comparten entre pestañas y ventanas emergentes del navegador. Si su sistema requiere acceder al mismo dominio (www.example.com/?code=site1 y www.example.com/?code=site2), las cookies podrían entrar en conflicto entre las pestañas.
Para superar esta limitación, puede ser necesario enviar el identificador de sesión en la URL. Si es posible, utilice site1.example.com o site2.example.com para evitar conflictos de dominio en las cookies. Esto podría generar costos adicionales por la necesidad de certificados SSL adicionales.
Este comportamiento se puede observar en muchos sitios web al abrir otra pestaña e intentar realizar búsquedas simultáneas. Una de las sesiones quedará inutilizable.
Los identificadores de sesión en GET y POST quedaron obsoletos en PHP 8.4 y se eliminarán en PHP 9.0. [ 2 ]
Mejor solución: Confirmación de identidad
Este ataque puede evitarse en gran medida cambiando y regenerando el ID de sesión cuando los usuarios inician sesión. Si cada solicitud específica de un usuario requiere que este se autentique ("inicie sesión") en el sitio, un atacante necesitaría conocer el ID de la sesión de la víctima. Sin embargo, cuando la víctima visita el enlace con el ID de sesión fijo, deberá iniciar sesión en su cuenta para realizar cualquier acción "importante" como si fuera ella misma. En ese momento, su ID de sesión cambiará y el atacante no podrá realizar ninguna acción "importante" con el ID de sesión anónimo.
Se puede utilizar una técnica similar para solucionar el problema del phishing . Si el usuario protege su cuenta con dos contraseñas, el problema se puede resolver en gran medida.
Esta técnica también resulta útil contra los ataques de falsificación de solicitudes entre sitios (CSRF) .
Solución: Almacenar los identificadores de sesión en cookies HTTP.
En la mayoría de los sistemas modernos, el identificador de sesión se almacena por defecto en una cookie HTTP , que ofrece un nivel de seguridad moderado siempre que el sistema de sesiones ignore los valores GET/POST. Sin embargo, esta solución es vulnerable a la falsificación de solicitudes entre sitios y no cumple con el requisito de ausencia de estado de REST .
Solución: Utilizar el identificador de sesión SSL/TLS.
Al habilitar la seguridad HTTPS , algunos sistemas permiten que las aplicaciones obtengan el identificador de sesión SSL/TLS . El uso de este identificador es muy seguro, pero muchos lenguajes de desarrollo web no ofrecen una funcionalidad integrada robusta para ello.
Regenerar el SID en cada solicitud
Una contramedida contra la fijación de sesión consiste en generar un nuevo identificador de sesión (SID) en cada solicitud. De esta forma, aunque un atacante logre engañar a un usuario para que acepte un SID conocido, este será inválido cuando el atacante intente reutilizarlo. La implementación de este sistema es sencilla, como se demuestra a continuación:
- Obtenga el identificador de sesión anterior
OLD_SIDde la solicitud HTTP. - Si
OLD_SIDes nulo, está vacío o noOLD_SIDexiste ninguna sesión con SID=, cree una nueva sesión. - Genera un nuevo identificador de sesión
NEW_SIDcon un generador de números aleatorios seguro. - Que la sesión se identifique mediante SID=
NEW_SID(y ya no mediante SID=OLD_SID). - Transmitir el nuevo SID al cliente.
Ejemplo:
Si Mallory logra engañar a Alice para que 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 : victim.example.comvictim.example.comacepta SID=I_KNOW_THE_SID, lo cual normalmente sería malo. Sin embargo, victim.example.comes seguro porque realiza la regeneración de la sesión. victim.example.comobtiene la siguiente respuesta:
HTTP / 1.1 200 OK Set-Cookie : SID=3134998145AB331FAlice utilizará ahora SID=3134998145AB331Falgo que Mallory desconoce y que SID=I_KNOW_THE_SIDno es válido. Por lo tanto, Mallory fracasa en su intento de fijación de sesión.
Lamentablemente, la regeneración de la sesión no siempre es posible. Se sabe que surgen problemas al usar software de terceros, como ActiveX o applets de 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 las 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 utilizando un identificador de sesión antiguo e inválido de una solicitud anterior.
Acepte únicamente SID generados por el servidor.
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 mencionó anteriormente, esto no evita todos los ataques de fijación de sesión.
if ( ! isset ( $_SESSION [ 'SERVER_GENERATED_SID' ])) { session_destroy (); // Destruir todos los datos de la sesión } session_regenerate_id (); // Generar un nuevo identificador de sesión $_SESSION [ 'SERVER_GENERATED_SID' ] = true ;Función de cierre de sesión
La función de cierre de sesión es útil, ya que permite a los usuarios indicar que no se deben realizar más solicitudes durante la sesión. Por lo tanto, los ataques solo pueden ser efectivos mientras la sesión esté activa. Cabe destacar que el siguiente código no realiza comprobaciones de falsificación de solicitudes entre sitios (CSRF) , lo que podría permitir a un atacante forzar a los usuarios a cerrar sesión en la aplicación web .
if ( cerrar sesión ) { session_destroy (); // Destruir todos los datos de la sesión }Tiempo fuera de los viejos SID
Esta medida de seguridad es sencilla de implementar y tiene la ventaja de proporcionar cierto grado de protección contra el acceso de usuarios no autorizados a la cuenta de un usuario autorizado mediante el uso de un equipo que pueda haber quedado desatendido.
Almacena una variable de sesión que contenga la marca de tiempo del último acceso realizado por ese SID. Cuando se vuelva a usar ese SID, compara la marca de tiempo actual con la almacenada en la sesión. Si la diferencia es mayor que un valor predefinido, por ejemplo, 5 minutos, finaliza la sesión. De lo contrario, actualiza la variable de sesión con la marca de tiempo actual.
Destruir la sesión si el remitente es sospechoso
Al visitar una página, la mayoría de los navegadores web establecen el encabezado Referrer , que indica la página que contenía el enlace que seguiste para llegar a esta página.
Cuando el usuario inicia sesión en un sitio que no suele tener enlaces externos (por ejemplo, sitios web bancarios o de correo electrónico ), y no se trata de un sitio donde los usuarios permanezcan conectados durante mucho tiempo, el Referer debería ser de ese sitio. Cualquier otro Referer debe considerarse sospechoso. Sin embargo, si la solicitud de origen proviene de una página HTTPS, el Referer se eliminará, por lo que no se puede confiar en este sistema de seguridad.
Por ejemplo, http://vulnerable.example.com/se podría emplear la siguiente comprobación de seguridad:
if ( strpos ( $_SERVER [ 'HTTP_REFERER' ], 'http://vulnerable.example.com/' ) !== 0 ) { session_destroy (); // Destruir todos los datos de la sesión } session_regenerate_id (); // Generar un nuevo identificador de sesiónVerifique que la información adicional sea coherente a lo largo de toda la 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 dificulta la fijación de sesión y otros ataques.
A medida que más y más redes adoptan la RFC 3704 y otras prácticas contra la suplantación de identidad , la dirección IP se vuelve más confiable como identificador de "misma fuente". Por lo tanto, la seguridad de un sitio web puede mejorarse verificando que la dirección IP de origen sea consistente durante toda la sesión.
Esto podría realizarse de esta manera:
if ( $_SERVER [ 'REMOTE_ADDR' ] != $_SESSION [ 'PREV_REMOTEADDR' ]) { session_destroy (); // Destruir todos los datos de la sesión } session_regenerate_id (); // Generar un nuevo identificador de sesión $_SESSION [ 'PREV_REMOTEADDR' ] = $_SERVER [ 'REMOTE_ADDR' ];Sin embargo, hay algunos puntos a considerar antes de emplear este enfoque.
- Varios usuarios pueden compartir una misma dirección IP. No es raro que un edificio entero comparta una misma dirección IP mediante NAT .
- Un usuario puede tener una dirección IP inconsistente. Esto ocurre con los usuarios que utilizan servidores proxy (como los clientes de AOL ). También sucede con algunos usuarios móviles o en roaming, así como con usuarios que utilizan conexiones a Internet con balanceo de carga. Los usuarios con las extensiones de privacidad IPv6 activadas también pueden cambiar sus direcciones IPv6 en cualquier momento.
- No funcionará de forma fiable con clientes de doble pila, ya que las solicitudes se moverán entre IPv4 e IPv6.
- No funcionará de forma fiable con usuarios de dispositivos móviles, ya que estos también se desplazan entre diferentes direcciones.
Para algunos sitios, la seguridad adicional compensa la falta de comodidad, y para otros no.
Agente de usuario
Los navegadores se identifican mediante encabezados HTTP "User-Agent". Este encabezado normalmente no cambia durante el uso; sería extremadamente sospechoso que lo hiciera. Una aplicación web podría utilizar la detección de User-Agent para intentar evitar que usuarios malintencionados roben sesiones. Sin embargo, esto es muy fácil de eludir, ya que un atacante puede capturar fácilmente el User-Agent de la víctima con su propio sitio y luego falsificarlo durante el ataque. Este sistema de seguridad propuesto se basa en la seguridad por ocultación .
if ( $_SERVER [ 'HTTP_USER_AGENT' ] != $_SESSION [ 'PREV_USERAGENT' ]) { session_destroy (); // Destruir todos los datos de la sesión } session_regenerate_id (); // Generar 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.
- Varios usuarios pueden tener el mismo agente de usuario del navegador en un cibercafé .
- Varios usuarios pueden tener el mismo navegador predeterminado (por ejemplo, Internet Explorer 6 en Windows XP SP3 o un mini navegador en un teléfono móvil).
Pero el agente de usuario puede cambiar legalmente en algunos casos. Los siguientes ejemplos corresponden a los mismos usuarios.
- Un teléfono inteligente cuya pantalla giró desde la última solicitud.
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 DROID2Mozilla/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
- Modo de compatibilidad de Internet Explorer:
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)
- Un usuario accede a un sitio web a través de un proxy distribuido en varios servidores, no todos actualizados a la última versión del software proxy.
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)
Defensa en profundidad
La defensa en profundidad consiste en combinar varias contramedidas. La idea es sencilla: si un obstáculo es fácil de superar, varios obstáculos podrían ser muy difíciles de superar.
Una estrategia de defensa en profundidad podría incluir:
- Habilitar HTTPS (para protegerse contra otros problemas)
- Configuración correcta (no aceptar SID externos, establecer tiempo de espera, etc.)
- Realizar la regeneración de la sesión, admitir el cierre de sesión, etc.
Los referentes HTTP no se transmiten con SSL/TLS (HTTPS).
El siguiente script PHP demuestra varias de estas contramedidas combinadas de forma estratégica, mediante una defensa en profundidad:
if ( isset ( $_GET [ 'LOGOUT' ]) || $_SERVER [ 'REMOTE_ADDR' ] !== $_SESSION [ 'PREV_REMOTEADDR' ] || $_SERVER [ 'HTTP_USER_AGENT' ] !== $_SESSION [ 'PREV_USERAGENT' ]) { session_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 compara la dirección IP (REMOTE_ADDR) y el agente de usuario actuales con los de la solicitud anterior. Esto podría resultar inconveniente para algunos sitios, como se mencionó anteriormente.
Véase también
Referencias
Enlaces externos
- Rincón de seguridad: Fijación de sesión
- Vulnerabilidad de fijación de sesión en aplicaciones web (PDF)
- Ejemplo de vídeo de fijación de sesión
- Clasificación de amenazas del Consorcio de Seguridad de Aplicaciones Web
- vulnerabilidades de seguridad web
