Lead Poisoning via Formulário Público (Smishing por Procuração)
O vetor
Vetor real: atacante descobre que seu formulário de captura de WhatsApp não valida quem é o dono do número informado. Ele envia centenas de leads com números de vítimas aleatórias. Seu n8n/CRM dispara mensagens em seu nome para pessoas que nunca pediram contato → sua marca vira vetor de spam, seu número de WhatsApp Business pode ser banido pela Meta, e você responde pela LGPD (art. 8 — consentimento ausente).
O que testamos: o /api/leads aceita um número de WhatsApp arbitrário sem nenhuma verificação de propriedade.
Os passos
Preparação:
BASE="https://seu-app.exemplo.workers.dev"
# Use um número que NÃO é seu (ex.: 5511999998888 — não atende)
# Use prefixo pentest_ em car_title para permitir a limpeza depois
Passo 1 — Enviar lead com telefone de terceiro:
curl -s -X POST "$BASE/api/leads" \
-H "Content-Type: application/json" \
-d '{
"name": "pentest_poison_test",
"whatsapp": "5511999998888",
"car_title": "pentest_lead_poison",
"car_id": "test-001",
"niche": "auto"
}' | python -m json.tool
O que esperar
Resultado esperado:
{
"success": true,
"message": "Lead registrado com sucesso! Um consultor entrará em contato em breve.",
"lead": {
"name": "pentest_poison_test",
"whatsapp": "5511999998888",
"car_title": "pentest_lead_poison",
...
}
}
✅ Confirmado ao vivo: o sistema aceitou e gravou. HTTP 201.
Passo 2 — Verificar se o lead foi persistido (service role):
cd /d/Antigravity-Monetizacao_TikTok/app
node -e "
(async()=>{
const fs=require('fs');
const env=Object.fromEntries(fs.readFileSync('.env.local','utf8').split(/\r?\n/).filter(l=>l.includes('=')).map(l=>[l.slice(0,l.indexOf('=')).trim(),l.slice(l.indexOf('=')+1).trim()]));
const SB=env.NEXT_PUBLIC_SUPABASE_URL, SRK=env.SUPABASE_SERVICE_ROLE_KEY;
const H={apikey:SRK,Authorization:'Bearer '+SRK};
const r=await (await fetch(SB+'/rest/v1/leads?select=name,whatsapp,car_title&car_title=ilike.*pentest*',{headers:H})).json();
console.log(JSON.stringify(r,null,2));
})()"
Resultado esperado: 1 row com whatsapp: "5511999998888" — um número que não é seu, gravado como lead válido.
Passo 3 — Verificar se o webhook foi disparado:
# Verifique no painel do n8n se um item "lead_captured" chegou
# Se LEAD_WEBHOOK_URL estiver configurada, o n8n pode ter ENVIADO uma mensagem
# para 5511999998888 em SEU nome — esse é o vetor crítico
Análise — o que isto significa:
- Qualquer pessoa pode preencher seu formulário com o telefone de qualquer outra pessoa.
- Se seu n8n envia WhatsApp automático ao receber o lead, você está enviando mensagens não consentidas para terceiros.
- A Meta pode banir seu WhatsApp Business por spam reportado pela vítima.
- A vítima pode reportar você à ANPD (LGPD art. 8 — consentimento livre, informado e inequívoco).
Como corrigir
Correção necessária (P1):
- OTP de WhatsApp: enviar um código de 6 dígitos via WhatsApp API para o número informado e só gravar o lead após confirmação (prova de propriedade).
- Rate limit por IP: máx. 3 leads por IP por hora (via
cf-connecting-ip). - hCaptcha/Turnstile: exigir token de captcha em todo POST de leads.
- Honeypot + tempo mínimo: rejeitar submissões em < 2s (bot preenche instantaneamente).
- Validação de formato BR: DDD válido + nono dígito + não-sequential (bloquear 0000000000, 1111111111).
Limpeza:
# Após concluir o teste, remova o lead de teste:
cd /d/Antigravity-Monetizacao_TikTok/app
node -e "
(async()=>{
const fs=require('fs');
const env=Object.fromEntries(fs.readFileSync('.env.local','utf8').split(/\r?\n/).filter(l=>l.includes('=')).map(l=>[l.slice(0,l.indexOf('=')).trim(),l.slice(l.indexOf('=')+1).trim()]));
const SB=env.NEXT_PUBLIC_SUPABASE_URL, SRK=env.SUPABASE_SERVICE_ROLE_KEY;
const H={apikey:SRK,Authorization:'Bearer '+SRK};
const d=await fetch(SB+'/rest/v1/leads?car_title=ilike.*pentest*',{method:'DELETE',headers:H});
console.log('DELETE:',d.status);
})()"