O que é DKIM?

O DomainKeys Identified Mail (DKIM) é um padrão da Internet que permite que uma entidade assuma a responsabilidade por uma mensagem em trânsito. A entidade pode ser a organização do autor da mensagem ou uma retransmissão.

A entidade assinante faz o hash do corpo da mensagem e a assina digitalmente, juntamente com um subconjunto de seus campos de cabeçalho usando sua chave privada. A chave pública da entidade assinante é publicada como um _domainkey DNS TXT Resource Record do domínio do assinante. O destinatário pode recuperar a chave pública do assinante com uma consulta DNS e tentar verificar a assinatura digital para determinar se a assinatura é válida.

TL; DR DKIM nos fornece o corpo da mensagem e os hashes de cabeçalho em uma bandeja de prata – assinados digitalmente pelo domínio de transmissão!

Vamos trabalhar com um exemplo e verificar manualmente a assinatura DKIM. Aqui está um exemplo de mensagem enviada pela interface da web do Gmail:

Exemplo DKIM

Exemplo de mensagem com assinatura DKIM

Como em muitos outros artefatos forenses, a verificação de assinaturas DKIM requer que a mensagem suspeita seja preservada em sua forma original. O Yahoo e o Gmail permitem que os usuários finais baixem a mensagem bruta por meio de sua interface da web. Nesse caso, usei o Forensic Email Collector para adquirir a mensagem no formato MIME, que é idêntico ao que obtemos diretamente da interface da web do provedor. Em seguida, removemos alguns campos de cabeçalho longos antes de tirar a captura de tela acima para maior clareza.

Vamos começar dissecando o campo de cabeçalho DKIM-Signature.

Assinatura DKIM

O campo de cabeçalho DKIM-Signature contém a assinatura da mensagem, além de informações sobre como essa assinatura foi calculada. Curiosamente, o próprio campo de cabeçalho DKIM-Signature que está sendo criado ou verificado é incluído no cálculo da assinatura – com exceção do valor de sua tag “b =”.

Assinatura DKIM: v = 1; a = rsa-sha256; c = relaxado / relaxado;
d = gmail.com; s = 20161025;
h = mime-version: from: date: id da mensagem: assunto: para;
bh = NuUVBkHAblnFrMSNaWdGtwpjr9poc3wM2sXMhd25sPE =;
b = gGpvUwVrIr1IBFW1gZyFDYqvIO63kM27v1T90W5YWsPeXuFHZVuKuaFBO28GkBQJsg
ogqFsLfIicvDiEs5hPQfuI3SiZmXgizbnNB85ikrNh8oekceHCzcE7Rp4fe9EBiyMOmk
VjG1b4q7h7HCqBWOh9zHIpkoT2n6JSK0VpH2nJulKy8YrnAyZAm8on5XAWWVB83OvvU7
w4f2UMWPeXZeNNdgk67KmmO9VT3NfwMX8WEhajxcu1ETLPIrsgxROz2GaoNJ4gqDOi / S
eZtiT + sTWDxpjkrIcTOygR3Lcgb8D8CELqZOvEr0M9ySimQsobTicF1wOERP2NvaigFP
rjVA ==

As tags da assinatura DKIM acima são as seguintes:

v = Indica a versão da especificação DKIM. Você deve esperar ver o valor “1” neste campo até o momento da redação deste documento.

a = O algoritmo usado para criar a assinatura. Nesse caso, é RSA-SHA256.

c = indica os algoritmos de canonização que foram usados ​​para o cabeçalho e o corpo. O algoritmo de canonização determina como o corpo e o cabeçalho são preparados para o hash – especialmente no que se refere à tolerância à modificação em trânsito. Discutiremos isso mais adiante.

Nesse caso, “relaxado / relaxado” indica que o algoritmo de canonização relaxada foi usado para o cabeçalho e o corpo. Um único valor como “c = relaxado” indicaria que “relaxado” foi usado para o cabeçalho e “simples” foi usado para o corpo – equivalente a “c =” relaxado / simples “.

d = Indica o domínio que reivindica a responsabilidade de transmitir a mensagem. Este é o domínio cujo DNS consultamos para obter a chave pública. Nesse caso, o domínio é “gmail.com”.

s = indica o seletor para o domínio. Nesse caso, “s = 20161025” indica que podemos consultar o registro TXT para 20161025._domainkey.gmail.com para obter a chave pública.

h = Isso nos diz quais campos de cabeçalho foram incluídos na assinatura. Nesse caso, a lista é Mime-Version, From, Date, Message-ID, Subject e To. Usaremos a mesma lista de campos de cabeçalho ao verificar a assinatura.

bh = Este é o hash do corpo da mensagem depois que ela foi canônica, na forma Base64.

b = Os dados da assinatura no formulário Base64.

Canonicalização

Vamos examinar os dois algoritmos de canonização para preparar corretamente o cabeçalho e o corpo para a verificação DKIM manual.

Canonicalização simples

O algoritmo simples tolera quase nenhuma modificação. Para o cabeçalho, o algoritmo simples apresenta os campos do cabeçalho exatamente como estão, sem mudar de maiúsculas e minúsculas, alterando o espaço em branco, etc. Para o corpo, o algoritmo simples remove todas as linhas vazias extras no final do corpo da mensagem.

Canonicalização relaxada

O algoritmo relaxado fornece melhor tolerância para modificações em trânsito. Para o cabeçalho, o algoritmo relaxado converte todos os nomes de campos de cabeçalho em minúsculas (por exemplo, “Assunto:” -> “assunto:”), desdobra todas as linhas, converte todas as seqüências de um ou mais caracteres de espaço em branco em um único espaço, remove todo o espaço em branco no final de cada valor do campo do cabeçalho e remove qualquer espaço em branco antes e depois dos dois pontos que separam o nome do campo do cabeçalho do valor (por exemplo, “assunto: teste” -> “assunto: teste”). Para o corpo, o algoritmo relaxado remove todo o espaço em branco nas terminações da linha e substitui todo o espaço em branco dentro de uma linha por um único espaço. Linhas extras vazias no final do corpo da mensagem também são removidas.

Você pode encontrar a documentação oficial com todos os detalhes aqui: RFC 6376 – Canonicalização .

Verificação DKIM

Agora que sabemos como interpretar o campo DKIM-Signature e como preparar o corpo e o cabeçalho para o hash, podemos tentar verificar a assinatura DKIM manualmente.

Etapa 1 – Hash corporal

A primeira etapa é canonizar o corpo da mensagem, fazer hash e compará-lo com o valor relatado na tag “bh =”. Uma incompatibilidade aqui significa uma falha instantânea – não precisamos prosseguir.

A versão canônica do corpo da mensagem, usando o algoritmo relaxado, tem a seguinte aparência:

Corpo de mensagem canônico

Corpo de mensagem canônico

Configurei meu editor de texto para mostrar quebras de linha e espaços para a captura de tela acima. Observe que o CRLF no final permanece.

Quando misturamos o texto acima usando SHA-256 (com base no valor da tag “a =”) e convertemos o resultado em Base64, encontramos NuUVBkHAblnFrMSNaWdGtwpjr9poc3wM2sXMhd25sPE = . Isso corresponde ao hash do corpo que foi incluído na tag “bh =” do campo de cabeçalho DKIM-Signature.

Já podemos ver o quão poderoso isso é. O campo de cabeçalho DKIM-Signature contém um hash do corpo da mensagem, que podemos verificar com muita facilidade sem precisar buscar a chave pública da entidade assinante.

Etapa 2 – Chave pública do assinante

A próxima coisa que devemos fazer é consultar o domínio do assinante e buscar sua chave pública. Vamos precisar da d = gmail.com e s = 20161025 valores para isso.

Um bom recurso para usar aqui é a ferramenta DKIM Record Lookup do MxToolbox. Quando preenchemos o nome de domínio com “gmail.com” e o seletor com “20161025”, obtemos a seguinte chave:

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAviPGBk4ZB64UfSqWyAicdR7lodhytae + EYRQVtKDhM + 1mXjEqRtP / pDT3sBhazkmA48n2k5NJUyMEoO8nc2r6sUA + / Dom5jRBZp6qDKJOwjJ5R / OpHamlRG + YRJQqRtqEgSiJWG7h7efGYWmh4URhFM9k9 + RMG / CwCgwx7Et + c8OMlngaLl04 / bPmfpjdEyLWyNimk761CX6KymzYiRDNz1MOJOJ7OzFaS4PFbVLn0m5mf0HVNtBpPwWuCNvaFVflUYxEyblbB6h / oWOPGbzoSgtRA47SHV53SwZjIsVpbq4LxUW9IxAEwYzGcSgZ4n5Q8X8TndowsDUzoccPFGhdwIDAQAB
 
Usaremos a chave pública acima, juntamente com a assinatura encontrada na tag “b =”, e a versão canônica do cabeçalho da mensagem para verificar a assinatura.

Etapa 3 – Canonicalize o cabeçalho da mensagem

Para preparar o cabeçalho da mensagem para verificação, precisamos escolher os campos de cabeçalho indicados na tag “h =” nessa ordem, adicionar o cabeçalho DKIM-Signature a essa lista (exceto o conteúdo da tag “b =” ) e execute-o pelo algoritmo de canonização (relaxado neste caso).

Depois que as etapas acima estiverem concluídas, o cabeçalho da mensagem canônica será da seguinte maneira:

Cabeçalho da mensagem após canonização

Cabeçalho da mensagem após canonização

Há algumas coisas a serem observadas aqui:

  1. O campo de cabeçalho DKIM-Signature inclui o hash do corpo (a tag “bh =”). Portanto, embora não incluamos o próprio corpo no processo de sinal / verificação, estamos incluindo o hash do corpo canônico.
  2. Os nomes dos campos de cabeçalho foram convertidos para minúsculas e os espaços em branco foram ajustados de acordo com o algoritmo de canonização relaxado.
  3. Não há caracteres CRLF no final do texto, após a tag “b =”.
  4. O valor da tag “b =” é excluído. Isso faz sentido porque a entidade assinante não tinha como saber o valor da tag “b =” (isto é, os dados da assinatura) até depois que a assinatura foi calculada. Portanto, o valor da tag “b =” não poderia ter sido usado no cálculo da assinatura.

Passamos agora o cabeçalho canonicalizado acima, a chave pública que obtivemos na etapa 2 e a assinatura fornecida na tag “b =” do campo DKIM-Signature para nossa função de verificação de assinatura. Usei o método RSACryptoServiceProvider.VerifyData () disponível no .Net para verificação de assinatura. Você pode usar um equivalente na sua linguagem de programação preferida.

O processo de verificação de assinatura determina o valor do hash na assinatura usando a chave pública e compara-o ao valor do hash do cabeçalho da mensagem canonizada. Nesse caso, os dois hashes correspondem e a assinatura é verificada.

Automação, alguém?

Embora seja ótimo saber como fazer isso, a verificação manual das assinaturas DKIM pode ser entediante. Você pode usar várias ferramentas de código aberto para adicionar alguma automação ao seu fluxo de trabalho de verificação DKIM. Se você usa o Perl, pode consultar o Mail :: DKIM :: Verifier . Se o Python é a sua opção, o dkimpy também é uma boa opção – lembre -se de como são manipulados vários cabeçalhos de assinatura DKIM.

Qual é a relevância forense?

As assinaturas DKIM nos fornecem algumas informações muito poderosas para trabalhar – o hash criptográfico do corpo da mensagem e um subconjunto dos campos de cabeçalho, assinados pelo domínio de envio. Mesmo que um caractere que não seja de espaço em branco seja alterado após a assinatura da mensagem, a assinatura DKIM falhará na verificação. Ao autenticar forensemente uma mensagem de email, um cabeçalho DKIM-Signature válido e uma assinatura verificada indicam que o corpo da mensagem e as partes assinadas do cabeçalho da mensagem não foram modificadas depois que a entidade assinante calculou a assinatura DKIM.

Um suspeito poderia resolver isso? Algumas maneiras que vêm à mente são obter acesso à chave privada da entidade assinante para assinar em seu nome, manipular o corpo e / ou o cabeçalho da mensagem sem alterar seus hashes (atualmente não é possível para o SHA-256) e remover o Assinaturas DKIM da mensagem manipulada. A última é simples, mas também seria bastante fácil de detectar quando a mensagem suspeita é comparada a outras mensagens do mesmo remetente no mesmo período de tempo.

Outra consideração de segurança é o uso da tag “l =”. Essa tag opcional no campo de cabeçalho DKIM-Signature indica o comprimento do corpo que foi incluído no hash criptográfico. Ausência dessa tag indica que todo o corpo foi picado. Se a tag “l =” for usada, o suspeito poderá anexar conteúdo fraudulento além do subconjunto de hash do corpo da mensagem sem falhar na verificação DKIM. O RFC 6376 possui uma seção sobre considerações de segurança, que é uma leitura interessante.

Finalmente, é importante observar o campo Authentication-Results: header Gmail inserido na mensagem após o recebimento (consulte RFC 7601 ). Esse campo de cabeçalho indica, entre outras coisas, que a verificação do DKIM foi bem-sucedida no momento em que o Gmail recebeu a mensagem e contém os primeiros 8 bytes dos dados da assinatura na tag “header.b =”. Se a mensagem foi manipulada, isso pode ser útil para determinar quando a manipulação ocorreu.

Conclusões

Os examinadores forenses devem prestar muita atenção às assinaturas DKIM ao autenticar emails. Adicionar a verificação automática da assinatura DKIM ao seu fluxo de trabalho seria um bom ponto de partida. Se a verificação DKIM falhar, é importante saber o motivo. Foi porque a chave pública da entidade assinante não está mais disponível em seus registros DNS ou os hashes do corpo ou do cabeçalho não coincidem?

A especificação DKIM tem bastante detalhes, e a maioria das ferramentas que encontrei não parece ter implementado todos os aspectos da especificação. Ao trabalhar com o DKIM, é importante conhecer os detalhes e poder executar a verificação manual conforme necessário, especialmente para cobrir casos extremos.

Referências:
RFC 6376: Assinaturas de DKIM (DomainKeys Identified Mail) – https://tools.ietf.org/html/rfc6376
RFC 5863: Desenvolvimento, implantação e operações de DomainKeys Identified Mail (DKIM) – https: //tools.ietf. org / html / rfc5863
RFC 7601: Campo do cabeçalho da mensagem para indicar o status de autenticação da mensagem – https://tools.ietf.org/html/rfc7601

 

Artigo traduzido de: https://www.metaspike.com/leveraging-dkim-email-forensics/