Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Para proteger uma aplicação frontend contra CSRF, o servidor precisa recusar qualquer ação alterada sem prova de que ela partiu da própria aplicação. O frontend ajuda enviando um token ou um cabeçalho, mas a decisão final é sempre do backend: se a requisição não for validada no servidor, a proteção não existe.

Por que o navegador torna o ataque possível

Em aplicações autenticadas por cookies, o navegador envia automaticamente os cookies de um domínio em cada requisição dirigida a ele. Um site externo pode, portanto, induzir o navegador da vítima a disparar uma requisição, como um formulário oculto ou uma chamada a uma URL, e essa requisição chega ao seu servidor com a sessão válida da vítima. O atacante não lê a resposta; ele apenas consegue que a ação seja executada, como trocar um e-mail, alterar uma senha ou registrar uma compra.

Por isso a defesa não consiste em esconder o formulário nem em confiar no cabeçalho que o frontend envia. Ela consiste em garantir que o servidor só processe uma ação protegida quando puder verificar que a requisição veio de um contexto legítimo.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Escolha a técnica pela arquitetura da aplicação

A OWASP, em sua Cross-Site Request Forgery Prevention Cheat Sheet (OWASP Cheat Sheet Series), recomenda técnicas diferentes conforme a aplicação mantenha ou não estado de sessão no servidor. A tabela abaixo resume as opções e seus pontos de atenção.

Opção Melhor contexto Vantagem Ponto de atenção
Synchronizer token Aplicação com sessão no servidor O token é comparado com o estado da sessão; é o padrão recomendado pela OWASP para sistemas stateful Exige coordenação entre frontend e backend; token por requisição pode atrapalhar o uso de voltar e avançar do navegador
Double-submit assinado e vinculado à sessão Aplicação stateless ou em que guardar o token no servidor seja difícil Dispensa armazenar o token no servidor Exige criptografia e validação corretas; a versão ingênua é vulnerável a injeção de cookies
Fetch Metadata Navegadores modernos e endpoints que avaliam o contexto da requisição Verificação simples no servidor, sem mudança no cliente Precisa de fallback quando os cabeçalhos estão ausentes
SameSite no cookie Cookie de sessão em navegador compatível Reduz o envio do cookie em contextos cross-site Funciona como camada adicional, não como defesa única
Cabeçalho personalizado Frontend que chama uma API via JavaScript Encaixa-se bem em chamadas AJAX e fetch O backend precisa validar o cabeçalho; o token não pode ir para outra origem

Ao comparar as opções, avalie quatro pontos: se a aplicação mantém estado no servidor, quanta coordenação é necessária entre frontend e backend, quais clientes precisa atender e se existem subdomínios não confiáveis sob o mesmo domínio registrável. Esse último ponto costuma ser ignorado e muda bastante a escolha.

Antes de implementar, verifique o framework

A OWASP cita proteções CSRF embutidas em plataformas e frameworks. Antes de criar um mecanismo próprio, consulte a documentação oficial do framework que você usa e confirme se ela oferece proteção mantida pela equipe do projeto. Uma implementação integrada costuma ser preferível a uma artesanal, desde que atenda à sua arquitetura. Mesmo assim, ela precisa ser configurada corretamente, e o recurso deve estar ativo para todas as rotas que alteram estado.

Aplicações com sessão: synchronizer token

Esse padrão é o recomendado pela OWASP para software stateful. O servidor gera um valor secreto e imprevisível, guarda-o vinculado à sessão do usuário e exige que ele acompanhe cada requisição que altera estado.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Como implementar

  1. Gere o token no servidor com um gerador criptograficamente seguro e associe-o à sessão. Você pode usar um token por sessão ou um token por requisição; o primeiro evita problemas com o histórico do navegador.
  2. Entregue o token ao frontend, seja como campo oculto em um formulário HTML, seja em uma resposta JSON ou em um meta tag lido pelo JavaScript da aplicação.
  3. Envie o token de volta em um campo de formulário ou em um cabeçalho personalizado, como X-CSRF-Token, em cada método que altera estado: POST, PUT, PATCH e DELETE.
  4. No servidor, compare o valor recebido com o token guardado para a sessão. Se ele estiver ausente, vazio ou diferente, rejeite a requisição com status 403 e não execute a ação.

Se o usuário abrir a aplicação em duas abas, um token por requisição pode invalidar formulários antigos. Quando isso for um problema, prefira um token por sessão.

Rank #2
Sale
The Web Application Hacker's Handbook: Finding and Exploiting Security Flaws
  • Comes with secure packaging
  • It can be a gift item
  • Easy to read text

Aplicações stateless: double-submit cookie assinado

Quando não é prático guardar estado de token no servidor, a OWASP recomenda o padrão double-submit cookie. A ideia é enviar um valor no cookie e o mesmo valor em um campo ou cabeçalho da requisição, e o servidor confere se os dois coincidem.

Por que a versão ingênua falha

Se o servidor apenas compara o valor do cookie com o valor enviado, um atacante que consiga gravar um cookie no navegador da vítima, por exemplo a partir de um subdomínio sob seu controle ou por injeção de cookie, pode definir os dois valores. Por isso, em código novo, use a forma assinada e vinculada à sessão.

Como fazer a versão segura

  • Gere o token com HMAC usando uma chave que apenas o servidor conhece.
  • Inclua no conteúdo assinado um dado da sessão, como o identificador da sessão autenticada, para que um token válido em outra sessão não sirva na sua.
  • Compare os valores com uma função de comparação em tempo constante, e não com ==.
  • Nunca registre o token em logs, mensagens de erro ou ferramentas de monitoramento.

Enviando o token a partir do frontend

Em formulários HTML tradicionais, o token costuma viajar em um campo oculto. Em aplicações com JavaScript, a forma mais natural é um cabeçalho próprio, como X-CSRF-Token. Um cabeçalho configurado no cliente só protege algo se o servidor validar a requisição, e não ajuda em nada se o endpoint ignorar o cabeçalho.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Restrinja o envio do token aos endpoints do próprio serviço. Um cliente HTTP que anexa o token a todas as chamadas pode entregá-lo a outra origem, o que transforma um mecanismo de defesa em vazamento. O exemplo abaixo mostra uma chamada que envia o token apenas para a API da própria aplicação:

const token = document.querySelector('meta[name="csrf-token"]').content;

await fetch('/api/perfil', {
  method: 'PATCH',
  credentials: 'same-origin',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': token
  },
  body: JSON.stringify({ nome: 'Maria' })
});

Note que a chamada usa uma URL relativa ao próprio domínio. Se a URL vier de parâmetros controlados por terceiros, o token não deve ser anexado a ela (veja a seção sobre CSRF client-side).

Configure os cookies de sessão

Os atributos do cookie são uma camada importante, mas não substituem o token. Alguns pontos devem ser observados:

  • SameSite: defina explicitamente, normalmente Lax ou Strict, conforme o fluxo da aplicação. SameSite=None exige também Secure.
  • Secure: envia o cookie apenas por HTTPS. Use em qualquer aplicação em produção.
  • HttpOnly: impede que o JavaScript leia o cookie, o que protege a sessão contra roubo por XSS, mas não impede o CSRF.
  • Prefixo __Host-: o navegador só aceita o cookie se ele não tiver atributo Domain, tiver Path=/ e Secure. Isso limita a capacidade de subdomínios de sobrescrevê-lo.
Set-Cookie: __Host-sessao=valor; Path=/; Secure; HttpOnly; SameSite=Lax

A escolha entre Lax e Strict depende do seu fluxo. Com Strict, o cookie não acompanha navegações vindas de outros sites, inclusive links legítimos; com Lax, ele acompanha navegações de topo com métodos seguros.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Fetch Metadata e verificação de Origin ou Referer

O cabeçalho Sec-Fetch-Site informa ao servidor se a requisição veio da mesma origem, do mesmo site, de um site diferente ou de uma navegação direta. Para métodos que alteram estado, bloquear valores cross-site é uma verificação simples e útil. Segundo a própria OWASP, o Fetch Metadata é suportado em todos os principais navegadores desde março de 2023, com cobertura global declarada superior a 98%; a página consultada não indica a data de publicação dessa afirmação.

Clientes antigos ou incorporados podem não enviar esse cabeçalho. Por isso, a ordem de verificação recomendada é:

  1. Se Sec-Fetch-Site estiver presente, rejeite métodos que alteram estado quando o valor for cross-site.
  2. Se o cabeçalho estiver ausente, compare Origin com a origem esperada da aplicação.
  3. Se Origin também estiver ausente, use Referer como último recurso.

Antes de bloquear, teste fluxos legítimos de navegação, como retornos de pagamento ou links enviados por e-mail que terminem em uma ação. Esses fluxos costumam ser o motivo de falsos positivos.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

SameSite não substitui o token

SameSite é útil, mas tem limites que decidem onde o token ainda é necessário:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Ações que alteram dados feitas por GET continuam vulneráveis. A regra básica é que métodos seguros não alterem estado.
  • Requisições same-site vindas de subdomínios não são bloqueadas pelo atributo, porque o navegador as considera do mesmo site.
  • Se o JavaScript da própria aplicação for enganado para enviar uma ação, o cookie vai junto, pois a requisição parte de uma origem legítima.

Por isso, use SameSite como uma camada adicional, junto de token ou verificação de cabeçalhos nas ações sensíveis.

CSRF client-side: quando o JavaScript é o alvo

Esse é o caso menos intuitivo. Se a aplicação lê parâmetros da URL, como um destino de redirecionamento ou o caminho de uma chamada, e usa esses valores para decidir o método, o endereço ou o corpo de uma requisição autenticada, um atacante pode montar um link que faça a aplicação executar a ação desejada. Tokens e SameSite podem não impedir isso, porque o próprio JavaScript os envia.

A correção está no código da aplicação:

  • Não permita que parâmetros controlados pelo usuário determinem livremente o método HTTP, o destino ou o corpo de chamadas autenticadas.
  • Use listas de endpoints permitidos e mapeie ações a rotas fixas.
  • Valide destinos de redirecionamento contra uma lista de origens confiáveis.

Não coloque tokens em URLs

A OWASP alerta que tokens em URLs podem vazar pelo histórico do navegador, por arquivos de log e pelo cabeçalho Referer enviado a outros sites. Envie o token sempre em campo de formulário, cabeçalho ou corpo da requisição, e configure seus logs para não gravar esses valores.

Sequência prática de implementação

  1. Confirme que todas as ações que alteram estado usam POST, PUT, PATCH ou DELETE.
  2. Ative a proteção integrada do framework, se houver, e verifique se ela cobre todas as rotas.
  3. Escolha synchronizer token ou double-submit assinado conforme o estado da sessão.
  4. Configure os atributos dos cookies de sessão, incluindo Secure, HttpOnly e SameSite.
  5. Adicione verificação de Sec-Fetch-Site, com fallback para Origin e Referer.
  6. Revise o JavaScript em busca de destinos ou métodos definidos por parâmetros externos.
  7. Teste as ações sensíveis com uma requisição de outra origem e confirme que o servidor a rejeita.

A última etapa é a que mais falta nas equipes: um teste de regressão que tenta a ação sem token ou com origem externa mostra se a proteção está de fato ativa.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.