Email DFIR 101 — 电子邮件常规应急溯源
Email DFIR
前置知识
- 导出邮件原始文件(不是转发的,请从原始邮件的任意收件人邮箱中导出):会话式显示的邮件请选中对应的单独一封邮件导出。

- 邮件安全的三个重要机制:SPF、DKIM、DMARC
三个安全机制缺一不可,只配了 SPF 却没配 DMARC 等于没配,而 DMARC 配置的前提是 DKIM 和 SPF,所以缺一不可。
- 三个安全机制分别是什么鬼?
三个安全机制共同在 RFC 8616 被明确。另外某些老旧邮件服务器还会验证对应 IP PTR 记录中的域名匹配情况。
SPF:RFC 7208,简单来说就是有一个公开可查询的 DNS TXT 记录,记录了允许使用此域名发信的 IP 和服务器 Hostname ,由 SMTP 邮件服务器在 Transaction 开始时验证 MAIL FROM (MUST) / HELO (RECOMMENDED)
(即Envelop-From, P1 Sender)SMTP 命令中的域名和 DNS SPF 记录中是否一致,也会对此进行验证,部分邮件服务端还会检查邮件 Body 部分的 Return-Path 头。其对应的 TXT 记录查询一般使用 kdig +tls @1.0.0.1 TXT example.com


DKIM:RFC 6376,另一个公开可查询的 DNS TXT 记录,但是 DKIM 查询的需要一个 Selector,这个 Selector 由你的邮件服务提供程序或你自己定义,一般是 x
,不同的 Selector 用于发布多个签名用公钥,用于对服务器发送的电子邮件整体进行签名,由接收端邮件服务器验证。在 DNS 记录查询时通常可使用如下格式:kdig TXT x._domainkey.example.com +tls @1.0.0.1
。

DMARC:RFC 7489,标识当 SPF / DKIM 验证失败或验证成功时的操作及报告邮箱,可通过参数进行渐进式引入,支持 DMARC 标准的邮件服务商会定时发送相关记录和报告,查询方式:kdig TXT _dmarc.example.com +tls @1.0.0.1
。这里唯一需要注意的是,建议设置 fo=1
,这样在任意机制验证失败的情况下都会产生取证和警告报告,默认选项为0(在所有机制均验证失败才产生报告)。 DMARC 检测的是 Message-From 发件人,即 P2 Sender.

报告示例:
验证通过:

验证不通过:

报告可以通过 MXToolbox 解析,参见附录。各标准具体的选项含义可以参考附录部分的 Cloudflare 知识库或 RFC 文档。
应急查找溯源工具箱
仅列举直接与邮件本体相关的,附件等不在范围。
邮件头分析
微软 Exchange 服务器的邮件头分析推荐使用微软官方 MHA:https://mha.azurewebsites.net/
在对应邮件点击 View Source 或复制邮件头后提交至:https://mxtoolbox.com/EmailHeaders.aspx ,可以获得一个如下图所示的邮件投递分析流程及相关域名配置的解析检查,通过此类分析通常可以获得发件人使用的客户端、真实邮件地址、真实发件 IP 或发件服务器等相关信息,但与攻击者真实身份相关的信息不保证每封邮件都会存在:

在上面这封邮件的邮件头中就在第一个柱状图处最上方 From 记录了发件客户端 IP,邮件头 X-Authenticated-Sender 记录了伪造邮件发件人使用的真实发件邮箱地址。下方的各类信息帮助你检查了相关域名的 DKIM / SPF / DMARC 配置。唯一可惜的一点是,由于没有统一的 SPAM / DKIM 检查结果展示标准,各家厂商的邮件安全软件的检查结果在邮件头中的体现格式各不相同,没有解析出来,但也基本使用了常规易懂的英语表示,人肉观察解析也没有问题。
Web 配置查询
通过 MXToolbox 的 SuperTool 可以覆盖目前主流的几乎所有的可以远程检查的邮件服务器配置,此处以 DMARC 为例:

下下策 — “我也是大黑阔”系列
很不幸的是:你碰到了一个客户,这个客户即使出了很大的事情,也亏损了不少钱,甚至可能还惹上了官司,但是依然不当回事,过了很久各种痕迹都已经被常规活动掩盖殆尽之后才来找你,还想让你帮忙“验尸”☹️。
这种情况下,在邮件取证没有进展,但是又需要出具“尸检报告”的情况,可以考虑使用邮件服务以和攻击者相同的手段发送伪造邮件来完成此类工作。请注意,此类工作务必在取得客户书面明确同意后执行,以避免潜在的法务问题。
具体的工具参见附件中的压缩包,请将压缩包完整解压至独立目录并阅读源代码及注释后使用,环境依赖为 Python 3+,在 3.8 上测试可用。需要自备 1 个域名 + 1个发件服务 + 发件模版。只需要设置改动 Runtime Constant
和 Code
注释之间的代码即可使用。邮件内容 HTML 、纯文本、附件部分会分别使用 ./assets/forged-mail-data.html / .txt / .bin
下的内容填充,其中附件为可选项,其他内容为必选项,请自行查看代码。

这个工具在编写过程中踩了一些坑,一并记录:
- 发件服务为代发服务,会在邮件末尾添加 Unsubscribe 链接。
- 客户邮件打开了吗?点了吗?
第一个问题,可以通过在邮件末尾使用障眼法替换 Unsubscribe 链接和显示文字解决,具体见下。
第二个问题,邮件服务商通常提供追踪服务,直接配置好追踪域名后查看发件记录即可。或者如下所示,使用 DNSLog 或 HttpLog 服务 (推荐 Ceye) 添加一个 1px 的图片作为追踪即可。

- SPF 验证无法通过?代发服务提示邮件服务器不允许发件邮箱地址/发件IP?
发件 IP 不允许的情况请自行更换 IP。需要特别说明的是:大部分运营商和 VPS 提供商均封禁了 25 端口避免垃圾邮件滥发导致的 IP 黑名单,请自行发送工单申请解封或使用 465/2525 等非标准端口或未封禁端口发信。也请务必遵循服务提供商的 ToS 和 AUP 条款,在获得授权的情况下以非滥用形式发信。
SPF 验证无法通过问题,请自查你使用的发信域名(非伪造的发信域名)的 DNS SPF 配置,并在工具中使用对应的真实发件邮箱登陆,如下所示(画横线行是重点):

也请同时检查 SMTP HELO/EHLO
命令中的本机域名配置(此处默认为本地计算机的 Hostname,可能泄露个人信息,务必恰当配置;域名加上 .local
结尾是为了在某种意义上绕过针对 HELO/EHLO
域名的检测):

如果使用伪造发件人功能,请根据实际邮件服务提供商服务器检测情况使用或不使用 X-Authenticated-Sender / X-Sender
邮件头,并恰当配置 Return-Path
邮件头:

- 为啥我写的工具永远只有纯文本发信?
邮件 Body 部分没有正确设置 MIME 对应的 Content-Type 头为 text/html
。

- 自签的不受信任的 TLS 证书无法使用?
默认不验证 TLS 证书合法性并使用明文传输。

附录
- 在生产环境发送邮件测试:Elasticemail.com ,选择 Email API 即可,新用户 免费发信 100 封邮件,使用 Anonaddy 或类似服务作为注册邮箱可以无限试用,提供 SMTP 非标端口 / HTTP API 支持,用户和网络友好。
- DMARC 报告解析工具:https://mxtoolbox.com/DmarcReportAnalyzer.aspx
- 关于 SPF、DMARC、DKIM 记录的配置和一些解释(由 Cloudflare 提供):
- https://www.cloudflare.com/learning/dns/dns-records/dns-dmarc-record/
- https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/
- https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/
相关的 RFC:
- https://www.rfc-editor.org/rfc/rfc7208
- https://www.rfc-editor.org/rfc/rfc8616
- https://www.rfc-editor.org/rfc/rfc6376
- https://www.rfc-editor.org/rfc/rfc7489
- 邮件解析与测试发件工具:Mailtrap.io ,免费用户每月 500 封测试额度。
- 电邮的各类配置检查的All-in-One 工具箱: mxtoolbox.com
- 一个不错的邮件安全相关的服务提供商博客:https://dmarcly.com/
一些疑问与思考
RFC7489 — Extract Author Domain

这一部分中对电子邮件的 From 如何解析,解析后如何应用于 DMARC 检测,检测后如何处置,异常行为如何响应进行了详细的说明。可否利用类似异常行为的手段绕过某些限制?
RFC7208 — Checking Authorization

这一部分对邮件 SPF 的检查进行了一些说明,对其中使用了非标准的域名的情况和常见的一些需要注意的利用合法机制的绕过进行了举例,也不妨是一种绕过的思路。
在后面 2.6 节 Results of Evaluation 中提到:
A result of “none” means either (a) no syntactically valid DNS domain name was extracted from the SMTP session that could be used as the one to be authorized, or (b) no SPF records were retrieved from the DNS.
因此,在 HELO
或 MAIL FROM
中使用此类域名或许也是一种绕过方案。