CSRF — Forjar Requisição Autenticada
Cross-Site Request Forgery (CSRF) explora a confiança que um servidor deposita no navegador de um usuário autenticado. O atacante cria uma página maliciosa que, ao ser visitada, dispara uma requisição ao alvo usando os cookies da vítima já presentes no navegador.
Como funciona
1. Vítima faz login em bank.example.com — cookie de sessão é armazenado no navegador.
2. Vítima visita evil.example (link enviado por e-mail ou chat).
3. evil.example contém formulário oculto que envia POST para bank.example.com/transfer.
4. Navegador inclui o cookie de sessão automaticamente.
5. Banco processa a transferência como se fosse a vítima.
Exemplo de payload (ambiente fictício)
<!-- evil.example/trap.html -->
<form id="f" action="https://bank.example.com/transfer" method="POST">
<input name="to" value="attacker-account">
<input name="amount" value="5000">
</form>
<script>document.getElementById('f').submit();</script>
Requisição GET pode ser ainda mais simples com uma tag <img>:
<img src="https://bank.example.com/delete-account?confirm=yes">
Por que cookies sozinhos não bastam
O navegador envia cookies automaticamente com toda requisição cross-origin para o domínio correto. A sessão da vítima é válida — o servidor não consegue distinguir a requisição legítima da forjada sem controles extras.
Prevenção — Token CSRF
Gere um token imprevisível por sessão. Inclua-o em cada formulário e valide no servidor.
// Geração (PHP)
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
// No formulário HTML
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
// Validação no servidor
if (!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
http_response_code(403);
exit('CSRF detectado');
}
Prevenção — SameSite Cookie
Set-Cookie: session=abc123; SameSite=Strict; Secure; HttpOnly
SameSite=Strict: cookie não é enviado em nenhuma requisição cross-site.SameSite=Lax: enviado apenas em navegação de nível superior (link), não em POSTs cross-site.
SameSite é a defesa mais simples e eficaz para navegadores modernos.
Prevenção — Verificar Origin/Referer
# Django / qualquer framework
origin = request.headers.get('Origin', '')
if origin not in ALLOWED_ORIGINS:
return HttpResponseForbidden()
Defesas complementares
- Re-autenticar para ações críticas (transferências, troca de senha).
- APIs JSON com
Content-Type: application/json— formulários HTML não conseguem setar esse header cross-origin. - Double Submit Cookie: token no cookie e no corpo, comparados no servidor.
- Frameworks modernos (Laravel, Django, Rails) habilitam proteção CSRF por padrão — não desabilite.
O que CSRF não faz
CSRF não lê a resposta do servidor (same-origin policy bloqueia). O ataque age, não espiona — para roubar dados use XSS, não CSRF.