Este artículo incluye una lista de referencias generales , pero carece de suficientes citas en línea correspondientes . ( Abril de 2012 ) |
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 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 dependen de que los identificadores de sesión se acepten a partir de URL ( cadenas de consulta ) o datos POST.
Alice tiene una cuenta en el bancohttp://unsafe.example.com/
Mallory pretende quitarle a Alice el dinero del banco.
Alice tiene un nivel razonable de confianza en Mallory y visitará los enlaces que Mallory le envíe.
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 que 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.Un error común es creer 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:
http://vulnerable.example.com/
y verifica 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, sino del hecho de que un subdominio puede configurar cookies comodín y que esas cookies pueden afectar a otros subdominios.
Guión:
www.example.com
distribuye 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 Alicewww.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 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 entre 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 usar 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 omitir el inicio de sesión por completo.
Por ejemplo, supongamos que Mallory crea un usuario llamado A1ice en www.example.com e inicia sesión con ese usuario para capturar un identificador de sesión válido y actual. Luego, Mallory engaña a Alice con una URL de evil.example.com que fija esa cookie de sesión en el navegador de Alice (como se describió anteriormente) y redirige a www.example.com para finalizar una transacción en particular (o, de hecho, un uso más amplio). De este modo, Mallory puede ocultar la sesión de su inicio de 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 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 las pestañas y las ventanas emergentes del navegador. Si su sistema requiere que se lo conecte con el mismo dominio (www.example.com/?code=site1 y www.example.com/?code=site2), las cookies pueden entrar en conflicto entre sí en las distintas pestañas.
Puede ser 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 observar en muchos sitios al abrir otra pestaña e intentar realizar búsquedas en paralelo. Una de las sesiones quedará inutilizable.
Este ataque se puede evitar en gran medida modificando 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 saber el ID de la sesión de inicio de sesión de la víctima. Sin embargo, cuando la víctima visita el enlace con el ID de sesión fijo, necesitará iniciar sesión en su cuenta para hacer algo "importante" como ella 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 solucionar el problema del phishing . Si el usuario protege su cuenta con dos contraseñas, 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 requerida ] Sin embargo, esta solución es vulnerable a la falsificación de solicitudes entre sitios y no cumple con el requisito de apátrida 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 ofrecen una funcionalidad integrada sólida para ello.
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 un sistema de este tipo es sencilla, como se demuestra a continuación:
OLD_SID
a partir 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 engaña con éxito a Alice para que visite http://victim.example.com/?SID=I_KNOW_THE_SID
, esta solicitud HTTP se envía a victim.example.com
:
OBTENER /?SID=SÉ_EL_SID HTTP / 1.1 Host : victima.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 la sesión. victim.example.com
obtiene la siguiente respuesta:
HTTP / 1.1 200 OK Establecer cookie : SID=3134998145AB331F
Alice utilizará ahora SID=3134998145AB331F
una información que Mallory desconoce y SID=I_KNOW_THE_SID
que no es válida. Por lo tanto, Mallory no podrá 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 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 que la sesión se divida en dos sesiones independientes.
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 hacer que el botón "atrás" en la mayoría de los navegadores quede inutilizable, ya que el usuario estaría usando un identificador de sesión más antiguo 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 indicó 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 en la sesión } session_regenerate_id (); // Generar 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 lo tanto, los ataques solo 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 potencialmente permite que un atacante obligue a los usuarios a cerrar la sesión de la aplicación web.
if ( cerrar sesión ) { session_destroy (); // Destruir todos los datos en la sesión }
Esta defensa es fácil de implementar y tiene la ventaja de proporcionar una medida de protección contra usuarios no autorizados que acceden a la cuenta de un usuario autorizado mediante una máquina que puede haber quedado desatendida.
Almacenar una variable de sesión que contenga una marca de tiempo del último acceso realizado por ese SID. Cuando se vuelva a utilizar ese SID, comparar la marca de tiempo actual con la almacenada en la sesión. Si la diferencia es mayor que un número predefinido, por ejemplo 5 minutos, destruir la sesión. De lo contrario, actualizar 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 contiene el enlace que siguió para llegar a esta página.
Cuando el usuario ha iniciado sesión en un sitio al que no es probable que se acceda a través de enlaces externos (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 largo período de tiempo, el referente debe ser de ese sitio. Cualquier otro referente debe considerarse sospechoso. Sin embargo, si la solicitud de origen proviene de una página HTTPS, se eliminará el referente, por lo que no puede depender de 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 en la sesión } session_regenerate_id (); // Generar 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 dificulta un poco la fijación de la sesión y otros ataques.
A medida que más y más redes comienzan a cumplir con RFC 3704 y otras prácticas anti- spoofing , la dirección IP se vuelve más confiable como un identificador de "misma fuente". Por lo tanto, la seguridad de un sitio web se puede mejorar verificando que la dirección IP de origen sea consistente durante toda la sesión.
Esto se podría realizar de esta manera:
if ( $_SERVER [ 'REMOTE_ADDR' ] != $_SESSION [ 'PREV_REMOTEADDR' ]) { session_destroy (); // Destruir todos los datos en 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 tener en cuenta antes de emplear este enfoque.
Para algunos sitios, la seguridad adicional compensa la falta de conveniencia, y para otros no.
Los navegadores se identifican a sí mismos mediante encabezados HTTP "User-Agent". Este encabezado normalmente no cambia durante el uso; sería extremadamente sospechoso si eso sucediera. Una aplicación web podría hacer uso de la detección de User-Agent para intentar evitar que usuarios maliciosos roben sesiones. Sin embargo, esto es trivial 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 oscuridad .
if ( $_SERVER [ 'HTTP_USER_AGENT' ] != $_SESSION [ 'PREV_USERAGENT' ]) { session_destroy (); // Destruir todos los datos en 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 tener en cuenta antes de emplear este enfoque.
Sin embargo, 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)
This section possibly contains original research. (July 2019) |
La defensa en profundidad consiste en combinar varias contramedidas. La idea es sencilla: si un obstáculo es trivial de superar, varios obstáculos pueden resultar muy difíciles de superar.
Una estrategia de defensa en profundidad podría implicar:
Los referentes HTTP no se pasan con SSL/TLS (HTTPS).
El siguiente script PHP demuestra varias de estas contramedidas combinadas de manera que se pueda defender en profundidad:
si ( se establece ( $_GET [ 'CERRAR SESIÓN' ]) || $_SERVIDOR [ 'DIRECCIÓN_REMOTA' ] !== $_SESSION [ 'DIRECCIÓN_REMOTA_ANTERIOR' ] || $_SERVIDOR [ 'AGENTE_USUARIO_HTTP' ] !== $_SESSION [ 'AGENTE_USUARIO_ANTERIOR' ]) { destrucción_sesión (); }session_regenerate_id (); // Generar un nuevo identificador de sesión$_SESSION [ 'AGENTE_USUARIO_ANTERIOR' ] = $_SERVER [ 'AGENTE_USUARIO_HTTP' ]; $_SESSION [ 'ADD_REMOTA_ANTERIOR' ] = $_SERVER [ 'ADD_REMOTA' ];
Tenga en cuenta que este código compara la REMOTE_ADDR (la dirección IP del usuario) y el User-agent actuales con la REMOTE_ADDR y el User-agent de la solicitud anterior. Esto puede resultar inconveniente para algunos sitios, como se explicó anteriormente.