偽造電子郵件以及製造電子郵件炸彈的攻防探討
*本文作者:Macr0phag3,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。
前言
想必熟悉 kali 或者接觸過 smtp 相關分析的人都聽說過 Swaks 這個工具。它號稱 SMTP 界的瑞士軍刀。工具會使固然厲害,但是不知道原理總覺得缺了點什麼。於是我就用 Python 自己寫了一個類似的工具,加上了郵件炸彈的功能,順帶分析一波原理。
SMTP 協議
SMTP 協議即簡單郵件傳輸協議,屬於 TCP/IP 協議簇,它是一組用於由源地址到目的地址傳送郵件的規則,由它來控制信件的中轉方式。SMTP 伺服器則是遵循 SMTP 協議的傳送郵件伺服器,用來發送或中轉發出的電子郵件。
SMTP 模型如下:
簡單的通訊過程如下(以 163 郵箱為例;以下返回均為正常情況):
第一步是請求建立連線:
telnet: telnet 163mx03.mxmail.netease.com 25
返回: 220 163.com Anti-spam GT for Coremail System (163com[20141201])
第二步是開啟傳輸通道:
傳送: HELO <domain> <CRLF>
或 EHLO <domain/address-literal> <CRLF>
。有什麼區別呢?EHLO 更新一些,會返回 smtp 伺服器支援的命令,相對比 HELO 要有用,所以基本用的都是 EHLO。HELO / EHLO 命令用於主機介紹它自己,可以被翻譯為 Hello, I am <domain>.
返回: 250 OK
或:
250-mail 250-PIPELINING 250-AUTH LOGIN PLAIN 250-AUTH=LOGIN PLAIN 250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urz44XGUCa0xDrUUUUj 250-STARTTLS 250-SIZE 73400320 250 8BITMIME
可以看到,EHLO 返回資訊更加詳細。
第三步是 MAIL 命令:
傳送: MAIL FROM:<傳送者郵箱> <CRLF>
返回: 250 Mail OK
第四步是 RCPT 命令:
傳送: RCPT TO:<接受者郵箱>
返回: 250 Mail OK
第五步是 DATA 命令:
傳送: DATA <CRLF>
返回: 354 End data with <CR><LF>.<CR><LF>
然後就可以輸入郵件內容了,包括主題,郵件正文等等。
第五步結束後,服務端會返回郵件傳送成功與否的情況:
返回: <= 250 Mail OK queued as mx13,P8CowAB3KDAxa5tbCxAiEg--.29768S2 1536912177
這樣,一封簡單的郵件就發出去了。當然,郵件伺服器在這個過程中會做各種判斷,以免輕易接受垃圾郵件。
完整的演示如下:
<= 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 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFQXaMIUCa0xDrUUUUj <= 250-STARTTLS <= 250-SIZE 73400320 <= 250 8BITMIME => mail from:<[email protected]> <= 250 Mail OK => rcpt to:<手動打碼@163.com> <= 250 Mail OK => data <= 354 End data with <CR><LF>.<CR><LF> => to: 手動打碼@163.com => from: [email protected] => subject: 這是一封垃圾郵件 => => DKIM?聽上去很好吃 => SPF 不是防晒係數嗎 => 我覺得 SMTP 很安全啊 => 我們不存在垃圾郵件,那些都是正常的郵件 => 郵件炸彈也是不存在的 => . <= 250 Mail OK queued as mx3,NcCowADX4z1_bJtbcsNOQw--.37583S2 1536912511
郵箱結果:
那麼,說了這麼多 Telnet 發郵件,和正常發郵件的的方式很不一樣。我們都是通過 web 介面或者 GUI 發的,如下:
而我們使用 Telnet 直接發郵件,實際上是在模擬第二個 Send。
說清楚 SMTP 了,接下來說偽造郵件發件人。
偽造郵件發件人
回顧之前的 Telnet 發郵件的過程,我們可以看到,我們使用 mail from: 聲稱自己是 [email protected],而且 SMTP 協議本身也不要求對此宣告做認證,所以偽造就是這樣達成的。那麼,經過這麼多年的發展,廠商有對此做出了什麼努力來解決這一問題呢?
SPF:傳送方策略框架
SPF 是為了防範垃圾郵件而提出來的一種 DNS 記錄型別,它是一種 TXT 型別的記錄,它用於登記某個域名擁有的用來外發郵件的所有 IP 地址。傳送人向接收方傳送一封電子郵件後,郵件接收伺服器接收電子郵件並執行如下操作:
檢查哪一個域聲稱傳送了該郵件並檢查該域的 SPF 記錄的 DNS。
確定傳送伺服器的 IP 地址是否與 SPF 記錄中的某個已釋出 IP 地址相匹配。
對電子郵件進行打分:如果 IP 地址匹配,則郵件通過身份驗證並獲得一個正分。如果 IP 地址不匹配,則郵件無法通過身份驗證並獲得一個負分。然後,對現有的防垃圾郵件篩選策略和啟發式篩選應用這些結果。或者直接拒絕接受,返回 550 MI:SPF。
我們查一下 163 的 SPF 記錄:
> nslookup -q=TXT 163.com Server:202.117.112.3 Address:202.117.112.3#53 Non-authoritative answer: 163.comtext = "v=spf1 include:spf.163.com -all" Authoritative answers can be found from: 163.comnameserver = ns5.nease.net. 163.comnameserver = ns3.nease.net. 163.comnameserver = ns6.nease.net. 163.comnameserver = ns1.nease.net. 163.comnameserver = ns4.nease.net. 163.comnameserver = ns8.166.com. 163.comnameserver = ns2.166.com. ns1.nease.netinternet address = 123.58.173.177 ns3.nease.netinternet address = 220.181.36.234 ns4.nease.netinternet address = 123.125.48.245 ns5.nease.netinternet address = 121.195.179.18 ns6.nease.netinternet address = 52.215.24.44
v=spf1 include:spf.163.com -all
是什麼意思呢?
SPF 記錄包含在一個 TXT 記錄之中,格式如下:
v=spf1 [[pre] type [ext] ] ... [mod]
1、v=spf1:SPF 的版本。如果使用 Sender ID 的話,這個欄位就應該是 v=spf2
2、pre:定義匹配時的返回值。可能的返回值包括:
+: 預設值。在測試完成的時候表示通過。
-: 表示測試失敗。這個值通常是 -all,表示沒有其他任何匹配發生。
~: 表示軟失敗,通常表示測試沒有完成。
?: 表示不置可否。這個值也通常在測試沒有完成的時候使用。
3、type:定義使用的確認測試的型別:
include:包含一個給定的域名的測試。以 include:domain 的形式書寫。
all:終止測試序列。比如,如果選項是 -all,那麼到達這條記錄也就意味著測試失敗了。但是如果無法確定,可以使用”?all”來表示,這樣,測試將被接受。
ip4:使用 IPv4 進行驗證。這個可以以 ip4:ipv4 或 ip4:ipv4/cidr 的形式使用。
4、ext:定義對 type 的可選擴充套件。如果沒有這個欄位,那麼僅使用單個記錄進行問詢。
5、mod:這是最後的型別指示,作為記錄的一個修正值。
測試後有以下結果:
通過;SPF記錄指定要允許傳送的主機;接受
硬失敗;SPF記錄已將主機指定為不允許傳送;拒絕
軟失敗;SPF記錄已將主機指定為不被允許傳送但正在轉換;接受但標記
中性;SPF記錄明確指出,對有效性無關;接受
沒有;該域沒有SPF記錄,或者SPF記錄不對結果進行評估;接受
所以,當我們聲稱 [email protected] 向 163 傳送郵件的時候,163 會不予接受(因為 qq 是有 spf 記錄的):
<= 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 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2UFsDjanUCa0xDrUUUUj <= 250-STARTTLS <= 250-SIZE 73400320 <= 250 8BITMIME => mail from:<[email protected]> <= 550 MI:SPF 163 mx45,X8CowEB5qUXsdZtbeT4JTQ--.35331S2 1536914924 http://mail.163.com/help/help_spam_16.htm?ip=手動打碼&hostid=mx45&time=1536914924
DKIM 與 DMARC
DKIM 是一種防範電子郵件欺詐的驗證技術,通過訊息加密認證的方式對郵件傳送域名進行驗證。
DMARC 是一種基於現有的SPF和DKIM協議的可擴充套件電子郵件認證協議,在郵件收發雙方建立了郵件反饋機制,便於郵件傳送方和郵件接收方共同對域名的管理進行完善和監督。
感興趣的話可以自行查閱資料。
漏網之魚
又說了那麼多,那麼是否有了 SPF 可以一勞永逸呢?其實並不是。拿 163 與 qq 舉例,查到傳送方的 spf 記錄,並且是標記的是硬失敗,當然是最好的,直接進行判斷。但是如果傳送方用的是軟失敗甚至沒有 spf 記錄呢?比如 huawei.com 就是軟失敗:
huawei.com text = "v=spf1 ip4:45.249.212.32 ip4:45.249.212.35 ip4:119.145.14.93 ip4:58.251.152.93 ip4:194.213.3.17 ip4:206.16.17.72 ip4:45.249.212.255 ip4:45.249.212.187/29 ip4:45.249.212.191 ip4:185.176.76.210 ~all"
如果出現這樣的情況,就得看廠商怎麼做了,一般來說都是放行。
郵件炸彈
說完了偽造發件人,再來說說郵件炸彈。
電子郵件炸彈是最古老的匿名攻擊之一,通過設定一臺機器不斷的大量的向同一地址傳送電子郵件,攻擊者能夠耗盡接受者網路的寬頻。由於這種攻擊方式簡單易用,也有很多發匿名郵件的工具,而且只要對方獲悉你的電子郵件地址就可以進行攻擊,所以這是大家最值得防範的一個攻擊手段。
既然能偽造發件人,那麼傳送郵件炸彈看上去也不難。事實上的確如此。另外,由於大量的請求以及連結,會觸發接收方各種抵制。接下來通過郵件炸彈的三種不同的方式談談。
單執行緒
單執行緒,發就好了,拿起死迴圈就是幹: while 1: xxxx
多執行緒:短連線
短連線就是我們最容易想到的,多執行緒,每個執行緒發起一次連結請求,發完一封就停止。執行緒數少點還好,一多就瘋狂提示:421 Too many connections。在 ehlo antispam 的時候就被幹掉了。實測大多數情況,100 執行緒發 能成功 20 封就已經很好了。而且發完一封就釋放連結,蠻浪費的。而且在 smtp 伺服器對頻繁的連線請求很敏感的時候, ip 容易被 ban(如 qq)。
多執行緒:長連線
長連線:設定好執行緒數後,一旦 ehlo antispam 成功,就不停地重複 mail from 到 data,郵件傳送成功後也不釋放連結,一直髮。若接收方 smtp 伺服器強制釋放此連結,則重新 ehlo antispam。這樣的話,如果不手動停止,就會一直嘗試連結、發郵件。轟炸效率 plus。
email_hack
根據上述的原理以及想法,我自己寫了一個命令列的工具:email_hack
usage: email_hack.py [-h] -faddr FROM_ADDRESS -taddr TO_ADDRESS [-tnum THREADS_NUM] [-v VERBOSE] [-c CRAZY_MODE] optional arguments: -h, --helpshow this help message and exit -faddr FROM_ADDRESS, --from_address FROM_ADDRESS fake from address -taddr TO_ADDRESS, --to_address TO_ADDRESS the address you want to delivery -tnum THREADS_NUM, --threads_num THREADS_NUM how many threads you want -v VERBOSE, --verbose VERBOSE verbose level -c CRAZY_MODE, --crazy_mode CRAZY_MODE Keep sending fake email (** Use with caution **)
詳細內容可以到 gayhub 看看: ofollow" rel="nofollow,noindex" target="_blank">https://github.com/Macr0phag3/email_hack 。
偽造郵件效果:
163:
qq:
郵件炸彈效果:
防禦方法
偽造郵件發件人
廠商:對 spf 記錄採用 硬失敗 的標記。且驗證時預到軟失敗標記的時候,儘可能拒絕。有可能的話, 上DKIM 與 DMARC
使用者:對於很重要的郵件資訊,不妨檢視一下郵件原文。
若只有 一個 Received ,且列出的 IP 與宣稱的地址不一致,則就是偽造的。雖然 Received 頭可以偽造,但是新的 Received 頭會新增在訊息的頭部,所以,如果存在偽造的 Received,那麼它總是在後面。
若有多個 Received,第一個 Received 中 是正規的(網易、騰訊等等) SMTP 伺服器 轉發過的,那麼肯定是經過驗證的合法使用者才能轉發過來,因為這些廠商都不會開匿名轉發,此時只需要看 IP 與宣稱身份是否一致,一致就 OK。若看著就 不正規,則就要小心一些了。
舉2個例子:
未被偽造:
偽造:
郵件炸彈
對大量併發的連線請求,不但要拒絕,而且要禁止其 IP 一段時間。經過測試,qq 在大量請求後會進行封禁,163只是拒絕連線,返回類似 “請15分鐘後再試”,其實還是可以接著發起連線請求的… ╮(╯▽╰)╭。最後,在郵件多次傳送失敗的時候,直接斷開連線,不要保留通道,強制傳送端重新發起連線請求。
*本文作者:Macr0phag3,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。