O CSRF (Cross-Site Request Forgery, ou falsificação de requisição entre sites) é uma classe de ataque em que um site malicioso induz o navegador da vítima a enviar, sem o seu consentimento, uma requisição autenticada para uma aplicação na qual ela já está logada. O resultado é uma ação de mudança de estado — transferir dinheiro, trocar e-mail, alterar permissões — executada em nome do usuário legítimo, mas orquestrada pelo atacante. Neste artigo de Conhecimento explicamos, em profundidade e com exemplos, como o CSRF funciona, qual o seu impacto e quais defesas realmente resolvem o problema em aplicações web, APIs e SPAs.
O que é CSRF
CSRF explora uma premissa de confiança da web: o navegador anexa automaticamente os cookies de sessão de um domínio a toda requisição destinada àquele domínio, independentemente de qual página originou a requisição. Se um usuário está autenticado em banco.com.br e, em outra aba, abre um site controlado pelo atacante, esse site pode disparar uma requisição para banco.com.br. O navegador, obedientemente, envia junto o cookie de sessão válido — e o servidor, sem saber que a intenção não partiu do usuário, processa a ação como legítima.
A vulnerabilidade não está em roubar credenciais nem em interceptar tráfego. O atacante nunca chega a ver o cookie da vítima; ele apenas o utiliza indiretamente, por meio do navegador. Por isso o CSRF também é conhecido como session riding (cavalgar a sessão): o ataque monta sobre uma sessão já estabelecida e a conduz para onde o atacante quer.
O padrão catalogado é o CWE-352: Cross-Site Request Forgery, e o tema é tratado em profundidade pela comunidade no OWASP CSRF Prevention Cheat Sheet. Historicamente, o CSRF figurou como categoria própria no OWASP Top 10 (A8:2013); nas edições recentes ele foi absorvido pela categoria de Broken Access Control, refletindo que se trata, no fundo, de uma falha de controle de acesso à intenção do usuário.
Como o ataque funciona
Para que um CSRF tenha sucesso, três condições costumam estar presentes ao mesmo tempo:
- Ação relevante: existe uma operação que muda estado e interessa ao atacante (alterar e-mail, transferir valores, promover um usuário a administrador).
- Autenticação por cookie: a sessão é gerenciada apenas por cookies enviados automaticamente pelo navegador, sem nenhum segredo adicional que o atacante não possa prever.
- Parâmetros previsíveis: o atacante consegue montar toda a requisição de antemão, porque não há valores imprevisíveis (como um token) que ele precise adivinhar.
Considere um endpoint ingênuo de troca de e-mail que aceita um POST simples:
POST /conta/email HTTP/1.1
Host: app.exemplo.com.br
Cookie: sessao=abc123...
Content-Type: application/x-www-form-urlencoded
[email protected]
O atacante hospeda em seu próprio site uma página que reproduz exatamente essa requisição. Um formulário que se auto-submete é suficiente:
<form action="https://app.exemplo.com.br/conta/email" method="POST">
<input type="hidden" name="novo_email" value="[email protected]">
</form>
<script>document.forms[0].submit();</script>
Quando a vítima autenticada visita essa página — por um link em e-mail, uma imagem em um fórum, um anúncio malicioso — o formulário dispara. O navegador envia o POST para app.exemplo.com.br com o cookie de sessão válido anexado, e o e-mail de recuperação da conta passa a ser o do atacante. Em seguida, ele solicita "esqueci minha senha" e assume a conta.
Requisições GET que mudam estado são ainda mais fáceis de explorar: basta uma tag <img src="https://app.exemplo.com.br/transferir?para=atacante&valor=1000"> embutida em qualquer página. O navegador carrega a "imagem" e a transferência acontece silenciosamente. Essa é uma das razões pelas quais operações de mudança de estado nunca devem ser expostas via GET.
Impacto: ações sem consentimento
O impacto do CSRF é sempre a execução de uma ação de mudança de estado sem o consentimento do usuário, com a autoridade dele. A gravidade escala conforme o poder da conta comprometida e a criticidade do endpoint atingido:
- Tomada de conta: troca de e-mail ou senha, adição de chave de recuperação, cadastro de dispositivo confiável.
- Fraude financeira: transferências, pagamentos, alteração de dados bancários de recebimento.
- Escalonamento de privilégios: em um painel administrativo, forçar um admin logado a criar um novo usuário administrador ou desabilitar controles de segurança.
- Alteração de configuração: mudar regras de firewall, rotas de e-mail, integrações e webhooks — comprometendo a organização inteira.
Quando a vítima é uma conta privilegiada, um único CSRF bem-sucedido pode servir de trampolim para o comprometimento de todo o ambiente. Por isso o risco não deve ser medido apenas pela "simplicidade" do endpoint, mas pelo que a ação permite fazer no contexto de negócio.
Defesas eficazes contra CSRF
Não existe bala de prata única; a proteção robusta combina camadas. As mais importantes estão descritas a seguir e resumidas na tabela ao final desta seção.
Tokens anti-CSRF
A defesa canônica é o token anti-CSRF: um valor imprevisível, gerado pelo servidor, que precisa acompanhar cada requisição de mudança de estado. Como o atacante não consegue ler nem adivinhar esse token (a política de mesma origem do navegador impede que ele leia respostas de outro domínio), ele não consegue montar uma requisição válida. Há dois padrões principais:
- Synchronizer Token Pattern
- O servidor gera um token único por sessão (ou por requisição), armazena-o no lado do servidor e o insere em um campo oculto de cada formulário. A cada submissão, o servidor compara o token recebido com o armazenado. É o padrão mais forte, indicado para aplicações com sessão no servidor.
- Double-Submit Cookie
- O servidor emite o token em um cookie e a aplicação o reenvia também em um cabeçalho ou campo do formulário. O servidor apenas verifica se os dois valores coincidem, sem precisar guardar estado. É útil para arquiteturas sem sessão no servidor (stateless), desde que o token seja assinado/criptografado para impedir fixação por subdomínios.
Regras práticas: o token deve ser criptograficamente aleatório, ter entropia suficiente, ser vinculado à sessão do usuário e validado em todas as requisições que alteram estado (POST, PUT, PATCH, DELETE). Nunca envie o token via GET em URL, onde ele pode vazar por logs, histórico e cabeçalho Referer.
Cookies SameSite
O atributo SameSite instrui o navegador a não enviar o cookie em requisições originadas por outro site, atacando a raiz do problema. Há três valores:
SameSite=Strict: o cookie nunca é enviado em contextos cross-site, nem mesmo ao seguir um link de outro domínio. Máxima proteção, mas pode prejudicar a experiência (o usuário chega deslogado ao clicar em um link externo).SameSite=Lax: o cookie é enviado apenas em navegações de topo com métodos seguros (como umGETao clicar em um link), mas não emPOSTcross-site nem em requisições em segundo plano. É o padrão adotado pelos navegadores modernos e oferece bom equilíbrio.SameSite=None: envia o cookie em qualquer contexto (exigeSecure). Reservado para casos legítimos de uso cross-site — e que, por isso, precisam de outras defesas.
O SameSite=Lax como padrão dos navegadores mitigou boa parte dos ataques clássicos, mas não substitui os tokens: há navegadores e clientes antigos sem esse comportamento, e o Lax não protege ações desencadeadas por navegação de topo com GET de mudança de estado. Trate o SameSite como defesa em profundidade, não como único controle.
Verificação de Origin e Referer
Para requisições de mudança de estado, o servidor pode validar os cabeçalhos Origin e Referer, rejeitando o que não pertencer a uma lista de origens confiáveis. O Origin é enviado em requisições que mudam estado e é difícil de forjar por JavaScript. É uma verificação barata e valiosa como camada adicional, embora exija tratar casos em que o cabeçalho está ausente (proxies, políticas de privacidade).
Re-autenticação em ações sensíveis
Para operações de alto impacto — trocar senha, alterar e-mail de recuperação, autorizar um pagamento elevado, mudar dados bancários — exija uma prova adicional de intenção: reinserção da senha, confirmação por segundo fator (MFA) ou step-up authentication. Como o atacante não possui esse segredo momentâneo, a requisição forjada falha mesmo que todas as outras defesas caíssem.
| Defesa | Como protege | Quando usar |
|---|---|---|
| Synchronizer Token | Token secreto por sessão validado no servidor | Apps com sessão no servidor; proteção padrão para formulários |
| Double-Submit Cookie | Compara token em cookie vs. cabeçalho/campo | Arquiteturas stateless; APIs sem estado de sessão |
| SameSite=Lax | Navegador não envia cookie em POST cross-site | Baseline em toda aplicação; defesa em profundidade |
| SameSite=Strict | Cookie nunca sai em contexto cross-site | Cookies de sessão de apps sem fluxo de link externo |
| Origin/Referer | Rejeita requisições de origens não confiáveis | Camada adicional em endpoints de mudança de estado |
| Re-autenticação / MFA | Exige segredo momentâneo que o atacante não tem | Ações críticas: senha, e-mail, pagamento, privilégios |
| Custom header (SPA/API) | Cabeçalho que só JS de mesma origem pode enviar | APIs consumidas por SPAs via fetch/XHR |
CSRF em APIs e SPAs
Aplicações modernas frequentemente separam frontend (SPA) de backend (API). O risco de CSRF aqui depende de como a autenticação é transportada:
- Sessão via cookie: se a API autentica por cookie enviado automaticamente pelo navegador, ela permanece exposta a CSRF e precisa das mesmas defesas — tokens,
SameSitee verificação deOrigin. - Token em cabeçalho (Bearer): se o cliente envia o token de autenticação explicitamente em um cabeçalho
Authorization(armazenado, por exemplo, em memória da SPA), o navegador não o anexa sozinho a requisições cross-site — o que remove, na prática, o vetor clássico de CSRF. O preço é ter de proteger esse token contra roubo por XSS.
Uma técnica comum para APIs consumidas por SPAs é exigir um cabeçalho personalizado (por exemplo, X-Requested-With ou um cabeçalho próprio). Como só é possível adicionar cabeçalhos customizados via JavaScript de mesma origem — e requisições cross-site com cabeçalhos não simples disparam preflight CORS — o atacante não consegue reproduzi-los a partir de outro domínio. Configure o CORS de forma restritiva: não use Access-Control-Allow-Origin: * combinado com credenciais, e valide a lista de origens permitidas.
Relação com XSS
CSRF e XSS são falhas distintas, mas se retroalimentam. O CSRF explora a confiança que o servidor tem no navegador da vítima; o XSS explora a confiança que o navegador tem no código entregue pelo site. O ponto crítico é: qualquer defesa anti-CSRF é anulada por um XSS na mesma origem. Se o atacante consegue executar JavaScript no contexto da sua aplicação, ele lê o token anti-CSRF, forja o cabeçalho customizado e ignora o SameSite, porque as requisições passam a partir da própria origem legítima. Por isso, tratar XSS não é opcional: sem ele, o modelo de proteção contra CSRF é apenas parcial. Combine sanitização de saída, Content Security Policy e cookies HttpOnly com as defesas de CSRF descritas aqui.
Referências
- OWASP CSRF Prevention Cheat Sheet
- CWE-352: Cross-Site Request Forgery (CSRF)
- OWASP Top 10 — Broken Access Control
- Cross-Site Scripting (XSS)
Como a Decripte ajuda a sua empresa
Falhas de CSRF costumam passar despercebidas em revisões apressadas porque não "vazam dados" de forma óbvia — o dano aparece quando uma conta é sequestrada ou uma configuração crítica é alterada. Na Decripte, tratamos a superfície de OWASP Top 10 de ponta a ponta: revisão de código e arquitetura, testes de intrusão em aplicações web e APIs, e acompanhamento contínuo da postura de segurança de organizações de qualquer porte — de 1 a mais de 100.000 colaboradores. Ajudamos a definir onde aplicar tokens, como configurar SameSite e onde exigir re-autenticação, sem sacrificar a experiência do usuário. Você pode comece grátis avaliando o risco da sua superfície de ataque e, quando quiser evoluir para acompanhamento contínuo, conhecer nossos planos desenhados para o seu tamanho.
