Information Disclosure em Erros da API
O vetor
Vetor real: servidores que vazam stack traces, nomes de arquivos, versões de bibliotecas, e detalhes internos em mensagens de erro dão ao invasor o mapa exato de como explorar. "E guilty of information disclosure" é uma das falhas mais comuns — e uma das primeiras coisas que um invasor procura. O que testamos: se a API vaza arquitetura, versões, ou detalhes internos em respostas de erro e em respostas normais.
Os passos
Passo 1 — Vazamento de arquitetura na resposta normal do feed:
BASE="https://seu-app.exemplo.workers.dev"
curl -s "$BASE/api/feed?limit=1" | python -c "
import sys, json
d = json.load(sys.stdin)
print('Campos visíveis:', list(d.keys()))
print('source:', d.get('source', 'não presente'))
"
O que esperar
Resultado esperado:
Campos visíveis: ['items', 'nextCursor', 'source']
source: database
🔍 O campo "source": "database" revela que os dados vêm do Supabase/Postgres, não de cache/KV. Informa ao invasor que atacar o banco afeta o feed diretamente.
Passo 2 — JSON malformado (erro verboso?):
curl -s -X POST "$BASE/api/feed" -H "Content-Type: application/json" -d 'INVALID{{{' -w "\nHTTP %{http_code}\n"
Resultado esperado: HTTP 405 (Method Not Allowed) — o endpoint só aceita GET. ✅ Bom — não vaza stack trace.
Passo 3 — Parâmetro absurdo (overflow):
curl -s "$BASE/api/feed?limit=999999999" | python -c "
import sys, json
d = json.load(sys.stdin)
print('Items retornados:', len(d.get('items', [])))
print('Source:', d.get('source'))
"
Resultado esperado: ~25 items (cap aplicado). ✅ Bom — mas source: "database" ainda vaza. O cap impede DoS mas não esconde a arquitetura.
Passo 4 — Headers de resposta (vazamento de versão):
curl -s -I "$BASE/api/feed" | grep -i "x-powered-by\|server\|x-nextjs\|via"
Resultado esperado: x-powered-by pode estar presente (depende da config). Se vazar Next.js ou versão, informa ao invasor qual CVE tentar.
Passo 5 — Erro 500 com path inexistente na API:
curl -s "$BASE/api/feed/nonexistent/deep/path" -w "\nHTTP %{http_code}\n" | head -3
Resultado esperado: HTTP 404 (Next.js not-found page) ou HTTP 200 (fallback). ✅ Não vaza stack trace.
Passo 6 — Erro de login com SQL-like injection (information disclosure):
curl -s -X POST "$BASE/api/admin/auth/login" \
-H "Content-Type: application/json" \
-d '{"email":"admin'\'' OR 1=1 --","password":"x"}' | head -3
Resultado esperado:
{"error": "Credenciais inválidas"}
✅ Bom — mensagem genérica, não diferencia "user not found" de "wrong password" no texto (mas difere no tempo — já coberto no Ex. 28).
Análise — o que isto significa:
"source": "database"no JSON é disclosure leve — não é crítico, mas informa ao invasor que não há cache intermediário.- Sem stack traces visíveis ✅ — a configuração de produção do Next.js suprime erros.
- Headers não vazam versão ✅ — Cloudflare Workers não envia
Server: nginxetc. - O disclosure principal é o
x-powered-by(se presente) e osourcefield.
Como corrigir
Correção necessária (P2):
- Remover
sourceda resposta — não expor se vem de DB ou cache:// Remover do response: // return Response.json({ items, nextCursor, source: 'database' }); // Trocar por: return Response.json({ items, nextCursor }); - Remover
x-powered-by: nonext.config.ts:export default { poweredByHeader: false, // ... }; - Error handler global: criar
app/api/error-handler.tsque sempre retorna{ "error": "Erro interno" }sem detalhes, logando o erro real apenas no servidor. - CSP
object-src 'none'ebase-uri 'self'para completar a CSP.