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 um GET ao clicar em um link), mas não em POST cross-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 (exige Secure). 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.

DefesaComo protegeQuando usar
Synchronizer TokenToken secreto por sessão validado no servidorApps com sessão no servidor; proteção padrão para formulários
Double-Submit CookieCompara token em cookie vs. cabeçalho/campoArquiteturas stateless; APIs sem estado de sessão
SameSite=LaxNavegador não envia cookie em POST cross-siteBaseline em toda aplicação; defesa em profundidade
SameSite=StrictCookie nunca sai em contexto cross-siteCookies de sessão de apps sem fluxo de link externo
Origin/RefererRejeita requisições de origens não confiáveisCamada adicional em endpoints de mudança de estado
Re-autenticação / MFAExige segredo momentâneo que o atacante não temAções críticas: senha, e-mail, pagamento, privilégios
Custom header (SPA/API)Cabeçalho que só JS de mesma origem pode enviarAPIs 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, SameSite e verificação de Origin.
  • 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

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.