Lead Poisoning via Formulário Público (Smishing por Procuração)

Só leitura — não altera nada no alvo. Só em alvo seu ou autorizado por escrito.

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):

  1. 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).
  2. Rate limit por IP: máx. 3 leads por IP por hora (via cf-connecting-ip).
  3. hCaptcha/Turnstile: exigir token de captcha em todo POST de leads.
  4. Honeypot + tempo mínimo: rejeitar submissões em < 2s (bot preenche instantaneamente).
  5. 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);
})()"

PurpleLab // plataforma de treino ofensivo + defensivo // Fase 1 — portal dinamico