
浅谈电子邮件伪造
前言
前两天朋友来问我关于钓鱼邮件的实现,用来给甲方做安全演练,他注册了一个跟甲方公司域名相似的域名,搭建了一个 ewomail,结果发现国内封 25 端口,没办法发信,后面叫他用阿里的企业邮箱免费版搞定了。
但引出了一个相关的技术问题,电子邮件发信人伪造
,早在2017年的时候,我用易语言 POST 相关在线伪造工具做过类似的软件,不过那时候啥也不懂,纯纯壳子,于是这两天我研究了一下。
本文仅作技术探讨,请勿用于违法犯罪!
SMTP
电子邮件协议主要包括SMTP、POP3和IMAP。
SMTP(Simple Mail Transfer Protocol)是用于在客户端与服务器、以及服务器之间发送和转发电子邮件的应用层协议,今天要讲的主角就是 SMTP 协议。
大概的通信过程如下:
1. 建立连接
- 客户端与服务器在 TCP 层建立连接,默认使用 25 号端口。
- 建立成功后,服务器发回
220
状态码,表示服务已就绪。 - 客户端发送
EHLO
(或HELO
)命令,告诉服务器自己的域名。 - 服务器回应
250
状态码,表示命令成功,并(在 EHLO 情况下)返回支持的扩展功能列表(如STARTTLS
,AUTH
等)。
2. 发送邮件
- 客户端发送
MAIL FROM:<发件人地址>
,指定邮件的发件人。 - 服务器返回
250
,确认发件人地址合法。 - 客户端发送一个或多个
RCPT TO:<收件人地址>
,指定收件人。 - 服务器对每个收件人均返回
250
,确认其合法。 - 客户端发送
DATA
命令,服务器返回354
,提示可以开始输入邮件数据。 - 客户端逐行发送邮件头和正文,最后以单独一行的句点
.
结束输入。 - 服务器返回
250
,表示邮件已成功接收并排队等待投递。
3. 关闭连接
- 客户端发送
QUIT
命令,请求断开会话。 - 服务器返回
221
,表示连接已正常关闭。
伪造原理
那么,为什么电子邮件可以伪造?其实原因很简单,因为在 SMTP 协议中,发件人的邮箱地址是可以由发信方任意声明的,比如我发送一份邮件,实际上是发送了以下内容给收件方的邮箱服务器:
Date: Wed, 06 Aug 2025 14:57:55 +0800
To: example@example.com
From: 110@110.com
Subject: test Wed, 06 Aug 2025 14:57:55 +0800
Message-Id:
X-Mailer:
Content-Type: text/html
test
This is a test
其中 Message-Id 是消息ID,方便对邮件区分,X-Mailer 是发件工具,**Subject **是邮件标题,最下方的是邮件内容。
而 其中 To 代表的就是收信方的邮箱地址,From 代表的则就是 发信方 邮箱地址,所以也就是说我可以任意的修改 发信方 的邮箱地址,但大家早就考虑到了这一点,所以建立了以下几种 防范机制。
- SPF 记录: 发件人策略框架(SPF)记录列出被授权从特定域发送电子邮件的服务器。这样,如果有人编造了一个与某个域相关联的电子邮件地址,这个地址不会出现在 SPF 记录中,也不会通过认证。
- DKIM 记录: 域名密匙确认邮件(DKIM) 记录使用一对密钥进行身份验证:一个公钥和一个私钥。公钥存储于 DKIM 记录中,私钥对 DKIM 头进行数字签名。如果假冒电子邮件来自一个具有 DKIM 记录的域,无法使用正确的密钥签名,因而无法通过验证。
- DMARC 记录: 基于域名的消息认证报告与一致性(DMARC)记录包含 DMARC 策略,在检查 SPF 和 DKIM 记录后,告诉邮件服务器如何处理。域名所有者可以根据这些检查设置规则,决定是否阻止、允许或传递消息。由于 DMARC 策略会审查其他身份验证策略,并允许域所有者设置更具体的规则,因此这些记录为防止电子邮件假冒增加了另一层保护。
摘抄自 Cloudflare
本文主要围绕 SPF——发件人策略框架(Sender Policy Framework),通俗来说就是各家邮箱服务器给自己的域名加了一个TXT类型的 SPF 记录,里面会包含自家服务器 IP 的白名单,不在白名单内的就说明是来路不明的 IP。
实现伪造过程
利器 swaks
本文使用 swaks
工具进行发信,Ubuntu/Debian 跟 Redhat 系列的 Linux 发行版 直接用 apt 或者 yum 安装即可,Kali 应该是内置的。
sudo apt install swaks
sudo yum install swaks
Swaks 是一个用Perl 语言编写的命令行工具,它主要用于测试SMTP 服务器,也被称为“SMTP 瑞士军刀”。Swaks 能够模拟各种SMTP 事务,帮助用户调试SMTP 服务器设置、发送邮件、以及检查服务器的响应。它支持多种SMTP 协议版本、身份验证方式和传输方法,并且可以灵活地配置和脚本化,以满足不同的测试需求。
SPF 校验
解析记录格式示例
v=spf1 ip4:192.0.2.0/24 include:_spf.example.com redirect:example.net -all
- v=spf1:协议版本,必须且仅此
- ip4/ip6:允许的 IP 段,如
ip4:192.0.2.0/24
- a/mx:允许与域名 A 记录或 MX 记录匹配的主机
- include::引入并复用其它域的 SPF 规则
- redirect=domain:本域所有机制都未匹配时,改去检查
domain
的 SPF 记录 - 限定符(+、–、~、?):指定匹配结果,
- 无符号/
+
= Pass -
= Fail(硬拒绝)~
= SoftFail(标记可疑)?
= Neutral(不处理)
- 无符号/
- -all:所有未匹配者硬拒绝
查看SPF解析记录
要查看收件人邮件服务器有没有 SPF 记录直接 nslookup 即可。
可以看到 Gmail 是有 SPF 记录的,一般临时邮件服务很多都没有 SPF 记录,找一个来举例子。
比如 https://tempmail.so/:
确实是没有 SPF 记录。
先试试给谷歌邮箱发一份伪造过的邮件,使用命令:
swaks \
--from "admin@mail.pku.edu.cn" \
--to "example@example.com" \
--ehlo "pku.edu.cn" \
--header "X-Mailer: Gmail" \
--header "Content-Type: text/html; charset=UTF-8" \
--header "Subject: test" \
--body "test"
返回:
可以发现谷歌拒收该邮件,因为 IP 不在白名单内。
那么我们先挑一个软柿子捏捏,用临时邮箱做个测试,给 oryx08199@mailshan.com 邮箱地址发一份伪造邮件。
可以看到确实是收到了。
SPF 绕过
如果你想直接绕过 SPF,那直接给出答案吧,不可能。
但你可以通过其他方式绕过,比如 代发机制,本文仅对该方式说明,至于为什么,因为我也不知道还有什么方式,没有深究过。
代发机制
实现起来很简单,多加一个参数 --h-From
,该参数填写为你要伪造的发信人地址,而 --from
填写为你的真实发件人地址。
代发机制需要你通过一个邮局服务器进行发信,比如说 QQ、网易、谷歌邮箱等都可以,去设置里面打开一下 smtp 发信即可,此处不过多赘述,请自行搜索,关键字为: 如何设置 QQ邮箱 SMTP,你也可以用别家邮箱服务器,此处仅作示例。
- 测试命令:
swaks \
--from "username" \
--h-From "admin@pku.edu.cn" \
--to "example@example.com" \
--ehlo "pku.edu.cn" \
--header "X-Mailer: Gmail" \
--header "Content-Type: text/html; charset=UTF-8" \
--header "Subject: 北京大学录取通知书" \
--body @./test.html \
--server smtp.qiye.aliyun.com \
--au "username"
--ap "password"
from
为你真实的发件人账号,也就是 xxx@xxx.comh-from
为你需要伪造的发信人账号。ehlo
为域名,其实可以随便填写。header
是设置邮件头,Subject 表示邮件主题,也就是邮件的标题; X-Mailer 是发信工具,可以不填; Content-Type 可以不填,此处我是要发送 html 内容,所以需要设置为 html。body
为你要发送的内容,如果你要发送正文文件就用 @+文件名的方式,发纯文本的话直接 "发送内容"。server
此处就为你的邮局的 SMTP 服务器地址au
为你的登录用户名ap
为你的登录密码
可能需要强制手动输入密码,复制粘贴即可。
如果你需要发送附件的话就用attach
参数。
使用代发机制绕过的话其实有一点点小缺陷,那就是会显示 由 xxx 代发,各家邮箱显示效果也不一样,我对 谷歌、QQ、网易都测试过了,不过优点是你可以随意伪造,SPF 机制不会管你。
虽然有这点缺陷,但我感觉还是会有不少人上当。。。
结果如下:
- QQ邮箱
- 谷歌邮箱
- 网易邮箱
重大发现
QQ邮箱
测试发现 QQ邮箱 的 SPF 验证机制似乎有些搞笑,如果你的发件人域名没有 SPF 记录的话,QQ是会收信的。
也就是说,你可以伪造一些没有 SPF 记录的域名发件,比如 110.com(实测没问题)。
哈哈哈,我记得我17年的写的那个工具我也喜欢用 110@110.com 做测试,梦回当年了。
另外,如果你要伪造的发信地址域名有 SPF 记录的话,你加一级子域名就可以绕过,比如北京大学的域名 pku.edu.cn 有如下 SPF 记录:
ubuntu@VM-8-15-ubuntu:~/temp$ nslookup -type=TXT pku.edu.cn
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
pku.edu.cn text = "_hzos8v1tcdrxo5uk1i5qyl7pnu7w15x"
pku.edu.cn text = "v=spf1 ip4:162.105.129.0/24 include:spf.icoremail.net -all"
但你只需要加一个子域,举个例子,mail.pku.edu.cn,nslookup 查询一下,没有 SPF 记录。
ubuntu@VM-8-15-ubuntu:~$ nslookup -type=TXT mail.pku.edu.cn
Server: 127.0.0.53
Address: 127.0.0.53#53
Non-authoritative answer:
mail.pku.edu.cn canonical name = mail.lb.pku.edu.cn.
实际操作一下,使用以下命令给 "example.com" 发送一封假冒的 北京大学录取通知书。
swaks \
--from "admin@mail.pku.edu.cn" \
--to "example@example.com" \
--ehlo "pku.edu.cn" \
--header "X-Mailer: Gmail" \
--header "Content-Type: text/html; charset=UTF-8" \
--header "Subject: 北京大学录取通知书" \
--body @./test.html
虽然发件人的地址是 mail.pku.edu.cn
,但这确实也是北大的域名,不深究压根不知道。
好了,咱也是北大学子了😄
网易邮箱
当然,网易邮箱也有这个问题,并且网易邮箱还有一个更大的问题,那就是 不校验 SPF !!!
也不是不完全不校验吧,会收信,但会显示一段提示,告诉你可能被伪造过。
但,如果你像前面说的玩法,加一级子域名,就消除提示了。🤣
- 有伪造提示
- 无伪造提示
结语
看来国内的邮箱服务是不咋行呀... 特别是 QQ邮箱,当时因为 QQKey 的问题,只要你电脑上登录了 QQ,开发者就可以直接获取你的 QQKey,而 QQKey 可以直接进入你QQ账号的一切 Web 业务(SSO单点登录),比如 QQ空间、QQ邮箱 等业务,不过这应该也不算 QQ邮箱 的问题,严格意义上来说是 QQ 的问题,当时一堆 Steam 撸号器 也是这个原理,不过你QQ邮箱设置了独立密码就可以规避了。
其他厂商的邮箱我还没测试,希望会好一些,这里还是建议大家 Gmail 或者 Proton Mail 之类的为上吧,有钱的可以上收费的电子邮箱服务。
对了,我还发现,QQ邮箱的移动APP,还帮我贴心的加上了头像,这是进一步给我加可信度了🤣
- 感谢你赐予我前进的力量