Voltar ao blog
CybersecurityEmail SecurityDMARCSPFDKIMPenetration TestingPhishingBEC

Como um único registo de email mal configurado nos deixou enviar emails como o CEO — um teste de intrusão real e a solução

Um teste de intrusão real: enviámos um email ao diretor financeiro como o CEO e chegou à caixa de entrada. Como funciona e como corrigir SPF, DKIM e DMARC.

P
Davi Nunes
March 26, 2026Atualizado October 30, 202611 min de leitura

Durante um teste de intrusão de rotina para uma empresa de média dimensão, a nossa equipa de segurança encontrou algo que deixou o CTO do cliente em silêncio durante cerca de dez segundos, a meio da chamada.

Tínhamos acabado de enviar um email ao diretor financeiro da empresa a partir do endereço de email do CEO. Pedia uma transferência bancária urgente para um novo fornecedor. Chegou à caixa de entrada. Sem filtro de spam, sem banner de aviso, sem nenhuma mensagem de "este email pode ser suspeito". Tinha exatamente o mesmo aspeto de qualquer outro email que o CEO alguma vez tivesse enviado.

Fizemo-lo a partir de um portátil no Porto, com um único comando e sem acesso à infraestrutura de email da empresa. Sem palavras-passe, sem contas pirateadas, sem acesso interno. Apenas um registo DNS mal configurado que estava à vista de todos há mais de três anos. Da consulta DNS ao email entregue, tudo demorou menos de dois minutos.

Eis porque funcionou e como fechar a falha.

O que encontrámos

A empresa tinha uma configuração normal: uma plataforma de caixas de correio alojada para os colaboradores, um serviço de email transacional para notificações automáticas e uma plataforma de marketing para newsletters. O DNS tinha três problemas:

  • O DMARC estava em p=none. A política existia, mas dizia aos recetores para não fazerem nada quando uma mensagem falhava.
  • O SPF terminava em softfail (~all) em vez de hard fail (-all). Um servidor não autorizado recebia um veredicto de "suspeito", não uma rejeição.
  • O DKIM não estava configurado em todos os serviços de envio.

Ligámo-nos ao servidor de correio da empresa, encontrado através do registo MX público, na porta 25, que tem de estar aberta para o email funcionar. O servidor que recebeu a mensagem verificou o SPF e viu um softfail, verificou o DMARC e viu p=none, e entregou-a. Qualquer pessoa na internet podia ter feito o mesmo.

O registo DMARC decidiu o resultado: dos três, é o único que fala do endereço que o destinatário vê. É a falha por trás do Business Email Compromise (BEC): pagamentos a fornecedores falsos, alterações falsas de dados bancários, tudo sem nenhuma conta pirateada.

Como funciona a falsificação

Um email tem dois endereços de remetente:

  • O remetente do envelope, o MAIL FROM da conversa SMTP, guardado depois como Return-Path. O destinatário nunca o vê.
  • O cabeçalho From, o endereço que o cliente de email mostra. O SMTP não o verifica: quem envia pode escrever lá o que quiser.

Cada norma verifica uma coisa diferente:

  • O SPF verifica se o servidor que se liga pode enviar pelo domínio do remetente do envelope. Nunca olha para o cabeçalho From.
  • O DKIM verifica que a mensagem foi assinada com uma chave publicada sob algum domínio e que não mudou desde então. Esse domínio, o valor d= do cabeçalho DKIM-Signature, pode ser qualquer um.
  • O DMARC pergunta se um resultado SPF ou DKIM aprovado pertence ao domínio do cabeçalho From. Essa correspondência chama-se alinhamento: uma mensagem passa o DMARC se o SPF passar e o domínio do envelope estiver alinhado com o domínio do From, ou se o DKIM passar e o domínio d= estiver alinhado com ele. A política (p=none, quarantine ou reject) diz ao recetor o que fazer quando nenhuma das duas coisas acontece.

É por isso que o SPF sozinho não trava o ataque, nem com -all. Um atacante pode pôr o seu próprio domínio no envelope, com um registo SPF que passa, e o endereço do teu CEO no cabeçalho From. Só o DMARC percebe que esse aprovado pertence a outra pessoa.

As mensagens recebidas registam os veredictos no cabeçalho Authentication-Results. Uma falsificação de um domínio desprotegido:

text
Authentication-Results: mx.example.net;
       spf=pass smtp.mailfrom=attacker.example.org;
       dkim=none;
       dmarc=fail header.from=example.com

O SPF passou, para o domínio errado; o DMARC falhou. A entrega depende agora da política que o example.com publica.

Verifica o teu próprio domínio

Três consultas mostram o que um atacante vê (substitui example.com pelo teu domínio):

bash
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT s2026a._domainkey.example.com

A primeira devolve todos os registos TXT do teu domínio. Exatamente uma linha deve começar por "v=spf1; duas é um erro. Uma linha com várias strings entre aspas está bem: os registos longos são divididos em strings de 255 caracteres que os recetores voltam a juntar. Depois lê o final: -all (fail), ~all (softfail), ?all (neutral) ou +all (pass para qualquer um).

A segunda devolve o teu registo DMARC, por exemplo "v=DMARC1; p=none". Sem resposta, não há DMARC: cada recetor aplica o seu próprio critério e ninguém te envia relatórios. Duas respostas v=DMARC1 significam que os recetores não aplicam nenhuma política DMARC. Tudo o que fique aquém de p=reject, ou de quarantine como passo intermédio, deixa a porta aberta.

A terceira precisa de um seletor, e o DNS não permite listá-los. Tira-o de uma mensagem real: no cabeçalho DKIM-Signature, s=s2026a; d=example.com significa que a chave está em s2026a._domainkey.example.com. Repete para cada sistema que envia pelo teu domínio. A resposta deve conter v=DKIM1 e um valor p= longo; se for um CNAME para o teu fornecedor, aparece primeiro o destino. Um p= vazio indica uma chave revogada.

O difícil é saber que sistemas devem constar destes registos. Pede uma avaliação gratuita de email spoofing e a nossa equipa de segurança analisa os teus registos SPF, DKIM e DMARC, conta as tuas consultas SPF, lista todos os serviços que enviam pelo teu domínio e diz-te se hoje alguém o pode falsificar.

SPF: onde falha sem dar sinal

Um registo SPF correto enumera todos os sistemas autorizados a enviar pelo teu domínio e, no fim, um veredicto para tudo o resto:

text
example.com.  IN  TXT  "v=spf1 include:_spf.mail.example.net include:spf.crm.example.org ip4:203.0.113.25 -all"

Quatro erros explicam a maioria dos SPF avariados:

  • Dois registos SPF no mesmo nome. Acrescentar um remetente com um segundo registo v=spf1 em vez de editar o primeiro faz o SPF devolver permerror. Junta-os.
  • +all ou ?all. O primeiro autoriza a internet inteira. O segundo não afirma nada.
  • O limite de 10 consultas. include, a, mx, ptr, exists e redirect contam cada um como uma consulta, incluindo os que estão dentro dos registos que incluis; ip4, ip6 e all não contam. Com mais de 10, o resultado é permerror.
  • Remetentes esquecidos. Faturação, CRM, ticketing, o scanner que envia PDF por email, os alertas de monitorização, o formulário de contacto do site. No WordPress esse formulário costuma funcionar através de um plugin, que também faz parte da superfície de ataque do site.

Para contar, corre dig +short TXT sobre o destino de cada include. Imagina que o teu registo tem três includes e um mx: quatro consultas. Se o include da plataforma de caixas de correio tiver mais três, já vais em sete. Perto do limite, remove os remetentes que já não usas, passa os envios em massa para um subdomínio com registo próprio ou substitui a e mx pelos teus próprios intervalos ip4. Nunca coles os IP de um fornecedor no teu registo: mudam sem aviso.

Quando o DMARC já aplica a política, tanto ~all como -all são defensáveis. Alguns recetores atuam perante um hard fail de SPF antes de avaliarem o DMARC e rejeitam email reencaminhado que o DKIM teria salvado, por isso algumas equipas mantêm ~all. O que falha é ~all sem uma política DMARC aplicada, exatamente o estado que encontrámos.

Muitos remetentes alojados também põem o seu próprio domínio de devolução no envelope, por isso o SPF passa para eles e não fica alinhado. Um domínio de devolução personalizado sob o teu resolve isso; o DKIM com o teu domínio é mais robusto.

DKIM: um seletor por remetente

O DKIM costuma sobreviver a um reencaminhamento simples e o SPF não, por isso é a via de alinhamento em que te deves apoiar:

  • Um seletor por sistema de envio. A plataforma de caixas de correio assina com s2026a, o CRM com crm2026. Os sistemas nunca partilham uma chave, e dispensar um fornecedor significa apagar um registo.
  • Assina como o teu domínio. Muitas plataformas assinam com o seu próprio domínio até configurares a assinatura com domínio personalizado. Essa assinatura passa mas não alinha: o d= deve ser example.com ou um dos seus subdomínios.
  • Chaves RSA de 2048 bits. A norma DKIM exige pelo menos 1024 bits e recomenda 2048.

Para verificar o tamanho de uma chave publicada:

bash
dig +short TXT s2026a._domainkey.example.com | tr -d '" \n' | sed -n 's/.*;p=\([^;]*\).*/\1/p' | openssl base64 -d -A | openssl pkey -pubin -inform DER -noout -text | head -1

Procura Public-Key: (2048 bit) no resultado.

Roda as chaves com uma periodicidade que consigas cumprir, por exemplo duas vezes por ano, e de imediato se uma chave puder ter sido exposta:

  1. 1Publica uma chave nova com um seletor novo (s2026b).
  2. 2Depois de expirar o TTL do DNS, muda a assinatura para esse seletor.
  3. 3Mantém o registo antigo durante cerca de uma semana, para que o email atrasado continue a ser verificado, e depois revoga-o com um p= vazio ou apaga-o.

DMARC: de p=none a p=reject sem perder email

O p=none foi pensado para ser temporário: mostra-te quem envia pelo teu domínio antes de pedires aos recetores que bloqueiem alguém. Se ficar assim, reporta o ataque e entrega-o.

Fase 1: monitorizar

text
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"

Os recetores que suportam relatórios enviam relatórios agregados para o endereço rua, normalmente uma vez por dia, em XML comprimido. Uma caixa de correio noutro domínio tem de ser autorizada lá com um registo TXT "v=DMARC1" em example.com._report._dmarc.reports.example.net, ou não chega nenhum relatório.

Fase 2: ler os relatórios

Cada registo mostra quantas mensagens um IP de origem enviou com o teu domínio no From, e como correram:

text
<record>
  <row>
    <source_ip>198.51.100.42</source_ip>
    <count>318</count>
    <policy_evaluated>
      <disposition>none</disposition>
      <dkim>fail</dkim>
      <spf>fail</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>example.com</header_from>
  </identifiers>
  <auth_results>
    <dkim>
      <domain>crm.example.org</domain>
      <result>pass</result>
    </dkim>
    <spf>
      <domain>bounce.crm.example.org</domain>
      <result>pass</result>
    </spf>
  </auth_results>
</record>

É um remetente legítimo a falhar o DMARC: o CRM assina e trata as devoluções com o seu próprio domínio, por isso as duas verificações passam e nenhuma alinha. Classifica cada origem num de quatro grupos:

  • Teus e alinhados: feito.
  • Teus e a falhar: a tua lista de trabalho. Corrige cada um com DKIM com o teu domínio ou com um domínio de devolução personalizado.
  • Reencaminhadores e listas de correio: o SPF quebra ao reencaminhar; o DKIM sobrevive a menos que a mensagem seja alterada, como as listas costumam fazer. Não te cabe a ti corrigi-los.
  • Desconhecidos: consulta o IP (dig +short -x 198.51.100.42). É um remetente de que ninguém te falou ou alguém a fazer-se passar por ti; descobre qual antes de aplicares a política.

Um parser open source como o parsedmarc torna o XML pesquisável. Fica nesta fase até a lista de trabalho estar vazia durante um mês inteiro, para que a faturação de fim de mês apareça.

Fase 3: quarentena, de forma gradual

text
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-reports@example.com"

pct=25 põe em quarentena um quarto das mensagens que falham; as restantes recebem a política imediatamente mais fraca, aqui none. Sobe para 50 e depois para 100 (o valor por defeito), lendo os relatórios em cada passo.

Fase 4: rejeitar

text
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=reject; sp=reject; rua=mailto:dmarc-reports@example.com"

Duas tags merecem uma decisão:

  • sp= define a política para os subdomínios sem registo DMARC próprio; se a omitires, herdam o p=. Uma falsificação a partir de billing.example.com, um nome que nunca enviou email, não tem SPF nem DKIM para passar, por isso é a política de subdomínio que a trava. Um sp=reject explícito mantém-se enquanto ajustas o p=.
  • adkim= e aspf= definem o alinhamento. Ambos são relaxados por defeito (r): mail.example.com alinha com example.com. O estrito (s) exige correspondência exata; escolhe-o só quando todos os remetentes usam exatamente o teu domínio.

Domínios que não enviam email

Domínios estacionados, domínios com erros ortográficos registados por defesa e domínios de marcas antigas que só redirecionam o site são fáceis de falsificar porque ninguém olha para eles. Declara que não enviam nem recebem nada:

text
example.org.                            IN  MX   0 .
example.org.                            IN  TXT  "v=spf1 -all"
_dmarc.example.org.                     IN  TXT  "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:dmarc-reports@example.com"
example.org._report._dmarc.example.com. IN  TXT  "v=DMARC1"

O null MX (RFC 7505) diz que o domínio não aceita email, por isso os remetentes falham de imediato em vez de tentarem de novo. O SPF não autoriza nenhum servidor, o DMARC rejeita tudo o que alegue vir do domínio ou dos seus subdomínios, e a última linha, na tua zona principal, deixa os relatórios chegarem à tua caixa de correio.

Depois de p=reject: continua a vigiar

As configurações de email vão-se desviando com o tempo:

  • Mantém o rua para sempre. Revê os relatórios todas as semanas; cria alertas para uma origem nova a falhar em volume ou para um remetente legítimo cuja taxa de aprovação desce.
  • Controla os novos remetentes. Antes de uma ferramenta nova enviar pelo teu domínio: DKIM com o teu domínio, consultas SPF recontadas e uma mensagem de teste que mostre dmarc=pass.
  • Remove os remetentes que saem. Apaga o include e o seletor quando o contrato termina.
  • Controla as alterações ao DNS. Um segundo registo SPF costuma vir de uma edição apressada no painel do registrar. Se geres os teus próprios servidores BIND 9, o DNS Manager, a interface web open source da Privum para BIND 9, sujeita as alterações de registos a controlo de acesso por perfis e a um registo de auditoria.
  • Verifica a partir de fora. Corre isto a partir do cron ou do CI contra todos os teus domínios.
bash
#!/usr/bin/env bash
# Usage: check-mail-auth.sh example.com (exits 1 on failure)
set -eu
d="$1"
dmarc=$(dig +short TXT "_dmarc.$d")
dmarc_n=$(echo "$dmarc" | grep -ci '^"v=DMARC1' || true)
spf=$(dig +short TXT "$d" | grep -ci '^"v=spf1' || true)

[ "$dmarc_n" -eq 1 ] || { echo "FAIL $d: $dmarc_n DMARC records, expected 1"; exit 1; }
echo "$dmarc" | grep -Eq ';[[:space:]]*p=reject' || { echo "FAIL $d: DMARC is not at p=reject"; exit 1; }
[ "$spf" -eq 1 ] || { echo "FAIL $d: $spf SPF records, expected 1"; exit 1; }
echo "OK $d"

Os registos podem parecer certos e ainda assim deixar uma falha, como um subdomínio com o seu próprio registo DMARC permissivo. A prova é uma tentativa de falsificação contra o teu próprio servidor de correio: foi assim que encontrámos esta, durante um teste de intrusão.


Descobre se o teu domínio pode ser falsificado antes que outro o descubra. Marca uma avaliação gratuita de email spoofing: verificamos o SPF, o DKIM e o DMARC em todos os teus domínios, incluindo os estacionados, identificamos cada serviço que envia em teu nome e entregamos-te um plano faseado até p=reject que mantém as faturas e as newsletters a circular.