XUT_ / COURSES / PENETRATION TESTER

Samesite Cookie Bypass

Vista Previa

Profundicemos en el mecanismo crucial de defensa conocido como cookies SameSite. Estas cookies vienen con un atributo especial diseñado para controlar cuándo se mandan con peticiones cross-site. Implementar esta propiedad es una manera confiable de protegerse contra filtraciones de información de cross-origin, CSRF y XSS. Dependiendo del contexto de la petición, le dice al navegador cuándo transmitir la cookie. Los tres valores potenciales son Strict, Lax y None.

El nivel de protección más alto es strict, que garantiza que la cookie sólo se manda si la petición viene del mismo origen que la cookie. Lax permite el uso de la cookie en orígenes cruzados por especificación.


Diferentes Tipos de Cookies SameSite

  • Lax: Las cookies SameSite Lax son como un vecindario amigable. Ofrecen un nivel de protección moderado permitiendo cookies ser mandadas en niveles altos de navegación y métodos HTTP seguros, como GET, HEAD y OPTIONS. Esto implica que no serán mandadas en peticiones cross-origin con POST, ayudando a mitigar cierto tipo de ataques CSRF. Sin embargo, siguen estando presentes en peticiones GET iniciadas por sitios web externos, lo que puede suponer un riesgo si se guarda información sensible en las cookies.
  • Strict: Las cookies SameSite Strict actúan como guardias de seguridad. Ofrecen el nivel más alto de protección restringiendo las cookies para que sólo se puedan mandar por el propietario. Esto significa que las cookies sólo se mandan con peticiones que se originan del mismo sitio que configuró la cookie, previniendo efectivamente los ataques CSRF.
  • None: Las cookies SameSite None se comportan como trotamundos sin responsabilidades. Se mandan tanto como por el propietario como en peticiones cross-site, haciéndolas convenientes para escenarios donde las cookies necesitan ser accesibles a lo largo de diferentes orígenes. Sin embargo, para prevenir riesgos de seguridad potenciales asociados con esta configuración, las cookies None requieren del atributo Secure en true para que la petición se haga a través de HTTPS. Esto asegura que las cookies sólo se mandan en conexiones seguras.

La Aventura de Explotación Lax

  • Ahora que el atacante puede acceder a la cuenta del banco de Josh, su objetivo principal es cerrale su sesión para que no pueda hacer más transacciones.
  • Ha visto una cookie logout que se configura una vez que hace login, esta cookie está configurada como Lax, lo que significa que se mandará en todas las navegaciones de alto nivel con peticiones como GET.

Samesite Cookie Bypass

  • Aquí está el código del lado del servidor que valida la cookie y comprueba su valor. Basado en ese valor, el código cierra la sesión del usuario.
php
<?php
$cookieNames = array_keys($_COOKIE);
if($_COOKIE["logout"] == "xxxxxxx"){
	// Loop through each cookie and delete it
foreach ($cookieNames as $cookieName) {
// If it's desired to kill the session, also delete the session cookie.
session_destroy();
..
...
}
  • El script requiere un valor de cookie, pero depende por completo del tipo de valor de SameSite. Como está en Lax, no será reenviada a peticiones cross-site a excepción del alto nivel de navegación y peticiones GET.
  • Para cerrarle la sesión a Josh, el atacante puede mandar un email, haciéndose pasar por un representador del banco y persuadiéndolo para que participe en una encuesta para ganar un premio.

Samesite Cookie Bypass

  • Ve a mailbox.thm:8081 y abre el mail con la insignia roja titulado "Exclusive Opportunity: Complete Our Survey for a Chance to Win a Ferrari!".

Samesite Cookie Bypass

  • Verás que el payload CSRF de logout está construido usando el siguiente payload:
html
<a href="https://mybank.thm:8080/logout.php" target="_blank">Survey Link!</a>
  • El atacante debe hacer una simple petición GET a logout.php, ya que la cookie está configurada como Lax.
  • Como la cookie proviene de una fuente verificada y la cookie de logout también está configurada, Josh será expulsado de su sesión y no podrá volver a iniciar sesión (ya que cambiamos su contraseña en la tarea anterior).

  • El desarrollador del MyBank LLC no consideró el atributo SameSite para las cookies al escribir el código. El ataque hubiera podido ser evitado si el atributo SameSite hubiera sido configurado como Strict en vez de Lax.
  • Además, como pentester es esencial analizar cada atributo de la cookie configurada por el dominio. La mayoría del tiempo, pequeños errores de desarrollo en programación causan avenidas abiertas de explotación en una aplicación aparentemente segura.

Escenario Lax con POST - Encadenando el Exploit

Como pentester, es importante comprobar las cookies que son mandadas por el sitio web. Como la cookie configurada en el ejemplo anterior era Lax, era posible cerrar la sesión de cualquier usuario. Pero ese escenario es posible sólo con peticiones GET y no se puede hacer nada en caso de peticiones POST.

Inicialmente, cuando el atributo SameSite fue introducido para incrementar la seguridad web restringiendo cómo se mandan las cookies en peticiones cross-site, Google Chrome y otros navegadores no reforzaron un comportamiento por defecto para cookies sin el atributo SameSite especificado. Sin embargo, con el tiempo, Google Chrome cambió esto e hizo que el valor por defecto si no se especificaba explícitamente de otra forma, fuera SameSite=Lax.

Pero ¿qué pasa si queremos hacer una petición POST? ¿Podemos hacer algo? La respuesta es sí. Como pone en la documentación de Chrome:

[!QUOTE] "Chrome will make an exception for cookies set without a SameSite attribute less than 2 minutes ago. Such cookies will also be sent with non-idempotent (e.g. POST) top-level cross-site requests despite normal SameSite=Lax cookies requiring top-level cross-site requests to have a safe (e.g. GET) HTTP method."

Por lo que cualquier cookie que no esté configurada con el atributo SameSite y si el servidor lee o modifica la cookie será mandada en peticiones cross-site hasta que dicha cookie cumpla dos minutos de vida. Después de esos dos minutos pasará a ser tratada como Lax.

Después de revisar el código, podemos ver que hay una cookie isBanned que se configura después de iniciar sesión. El valor de dicha cookie determina si el usuario es banneado o no y le muestra un mensaje. Nuestro objetivo es cambiar el valor de la cookie una vez que el usuario hace click en el link malicioso. Aquí está el código del lado del servidor que realiza la validación.

php
if (!isset($_COOKIE['isBanned'])) { echo('&#60;script&#62;alert("isBanned cookie not found in request");&#60;/script&#62;'); 	exit(); }
if (isset($_POST['isBanned'])) {
	$status=$_POST['isBanned'];
     echo('<script>document.cookie="isBanned='.$status.'";</script>'); 
}
  • Hay una llamada POST API a index.php que acepta un parámetro isBanned y configura el valor de la cookie. Sin embargo, el código del lado del servidor espera la cookie para evitar ataques CSRF.
  • Si hay alguna petición cross-site a la página, no podemos ejecutar el script para crear la cookie directamente, ya que no habrá una cookie isBanned en nuestra petición.
  • Probemos lo siguiente. Iniciamos sesión usando GB82MYBANK5699:GB82MYBANK5697. Al iniciar sesión, el valor de isBanned será actualizado, por lo que necesitamos esperar dos minutos.
  • Después de dos minutos, abrimos el email llamado LAX+POST.

Samesite Cookie Bypass

  • Este email consiste de dos botones. El primero hará una petición POST a index.php para actualizar el valor isBanned de la cookie.
  • El primer botón usa el código:
javascript
<script>
function launchAttack(){ setTimeout(function(){bank.submit()},1000)
}
</script>
<form style="display:none" name="bank" 
method=post action="http://mybank.thm:8080/index.php">
<input name="isBanned" value="true">
<input type="submit">
</form>
  • Haz click en el botón y mira lo que pasa:

Samesite Cookie Bypass

  • Esto pasa porque la cookie isBanned no fue redirigida por el buscador durante la petición.
  • ¿Cuál es la solución aquí? Podemos explotar la funcionalidad de que Chrome manda las cookies en una petición web si han sido modificadas en los últimos dos minutos. Como pentester es esencial entender cada petición y respuesta. La cookie isBanned es actualizada en dos instancias, una durante el login y la otra durante el logout.
  • Podemos encadenar el proceso para asegurarnos de que el usuario visita el link de logout. Una vez que haya cerrado la sesión y la cookie isBanned sea actualizada, tenemos una ventana de 2 minutos para llamar a index.php. para actualizar el valor de isBanned.
  • Aquí está el código que hace que el usuario cierre sesión y hace una llamada a index.php con el valor de isBanned actualizado.
javascript
<script>
function launchAttackSuccess(){
let win = window.open("http://mybank.thm:8080/logout.php",'');
setTimeout(function(){win.close();bank.submit()},1000)
}
</script>
<form style="display:none" name="bank" 
method=post action="http://mybank.thm:8080/index.php">
<input name="isBanned" value="true">
<input type="submit">
</form> 
  • Haz click en el botón de Successful Attack el cual primero cerrará la sesión del usuario y luego hará una petición POST a index.php y actualizará el valor de isBanned. Chrome redirigirá la cookie en la petición ya que ha sido actualizada hace menos de dos minutos.