電子郵件欺詐防護之 SPF+DKIM+DMARC

zachke發表於2020-04-07

前言

早在之前,有收到一個白客的郵件,說我們傳送電子郵件的域名缺少安全檢查,讓我們最好補上對應的安全檢查:

 I'm an independent cyber security researcher i have found multiple issues in your website.

 Vulnerability : Missing SPF 


 I am just looking at your SPF records then found following. SPF Records missing safe check which can allow me to send mail and phish easily any victim.

 PoC:

 <?php

 $to = "VICTIM@example.com";

 $subject = "Password Change";

 $txt = "Change your password by visiting here - [VIRUS LINK HERE]l";

 $headers = "From: https://karve.io";

 mail($to,$subject,$txt,$headers);

 ?>
 SPF record lookup and validation for: xxx.com
複製程式碼

後面檢查了一下,發現確實是這樣子,我們的電子郵件沒有加上對應的安全檢查,很容易被別人冒發,從而有可能對我們的使用者造成嚴重的電子郵件欺詐。

傳送欺詐電子郵件的危害

舉個例子,黑客可以通過這個站點 emkei.cz 來冒充我們的官方 support 郵箱來傳送一些釣魚郵件給使用者。如果使用者信以為真,那麼就會對使用者的利益造成損失,這就是電子郵件欺詐

png

這時候我們的使用者就會收到這一封冒充的郵件,如果使用者相信了,就很容易被騙子給利用了。

png

所以電子郵件欺詐的危害性還是很高的。這方面的安全問題,一定要儘快解決。

電子郵件的缺陷

在解決這個問題的時候,我們要了解一下為啥電子郵件會有這個問題?

電子郵件系統的基礎是簡單郵件傳輸協議(Simple Mail Transfer Protocol, SMTP), SMTP是傳送和中繼電子郵件的網際網路標準. 但是, 正如1981年最初設想的, SMTP不支援郵件加密、完整性校驗和驗證發件人身份。

由於這些缺陷, 傳送方電子郵件資訊可能會被網路傳輸中的監聽者擷取流量讀取訊息內容導致隱私洩漏, 也可能遭受中間人攻擊(Man-in-the-Middle attack, MitM)導致郵件訊息篡改, 帶來網路釣魚攻擊. 為了解決這些安全問題應對日益複雜的網路環境, 郵件社群開發了諸多電子郵件的擴充套件協議, 例如STARTTLS, S/MIME, SPF, DKIMDMARC等協議。 當前的郵件服務廠商大都也是採用以上擴充套件協議的一種或幾種組合, 輔以應用防火牆、貝葉斯垃圾郵件過濾器等技術, 來彌補電子郵件存在的安全缺陷.

你可以理解為 SMTP 本身有毛病,機密性和安全性都不夠,所以就多了幾個外掛來幫他:

  1. 提高傳輸的機密性,包括端對端加密 --> STARTTLS, S/MIME
  2. 郵件的身份驗證 --> SPF, DKIM, DMARC

電子郵件欺詐本質上就是郵件接收端沒法判斷這一封郵件來源是否合法。所以這邊就涉及到了郵件的身份驗證這一塊。而且雖然STARTTLSSMTP-STS保證了郵件在傳輸過程中的加密, 防止遭受竊聽讀取, 但是其仍無法解決發件方身份偽造、訊息篡改等問題。 所以郵件的身份驗證這一塊尤為重要。

所以本節主要講 SPF, DKIM,DMARC 這三個協議的設定並結合我們的站點來實踐。

SPF

SPF 概念

發件人策略框架(Sender Policy Framework, SPF)是一種以IP地址認證電子郵件發件人身份的檢測電子郵件欺詐的技術, 是非常高效的垃圾郵件解決方案。SPF允許組織授權一系列為其域傳送郵件的主機, 而儲存在DNS中的SPF記錄則是一種TXT資源記錄, 用以識別哪些郵件伺服器獲允代表本網域傳送電子郵件。 SPF阻止垃圾郵件發件人傳送假冒本網域中的“發件人”地址的電子郵件, 收件人通過檢查域名的SPF記錄來確定號稱來自該網域的郵件是否來自授權的郵件伺服器。 如果是, 就認為是一封正常的郵件, 否則會被認為是一封偽造的郵件而進行退回。 SPF還允許組織將其部分或全部SPF策略委託給另一個組織, 通常是將SPF設定委託給雲提供商。

簡單的來說,這個協議就是去核實郵箱源IP地址然後匹配它的dns中txt記錄的spf資訊,如果查詢到,那麼就是合法的。如果沒有查詢到,那就郵件的來源有問題。這時候一般郵箱接收端就會有三種處理方式:

  1. 直接拒絕或者刪除
  2. 認為是垃圾
  3. 正常的收件箱,但是郵件會有?的等警告,告訴收件者無法驗證郵件的真實身份

至於哪一種,不同的郵箱接收端的策略不一樣。 下面的圖(網路圖片)說的很清楚:

png

SPF 設定

SPF 的設定非常簡單,直接在公共的 dns 上進行配置即可。因為我們站點的域名 dns 是在 aws 的 router 53 中設定的。 而且因為我們的傳送 mail 的郵箱有兩種:

  1. 傳送提醒郵件的 no-reply 郵箱, 這一類郵件是接的 aws 的 ses 服務傳送的,是程式自動傳送的
  2. 傳送營銷郵件的 support 和 sale 郵箱,這一類的郵箱是 gmail 郵箱,是人工傳送的

所以 ses 和 google 這兩個域名都要配置,所以我們就在 router 53xxx.com 這個二級域名中在原有的 TXT 記錄中,新增這一條:

"v=spf1 include:_spf.google.com include:amazonses.com -all"
複製程式碼

png

這樣子 SPF 就配置好了。 是不是非常的簡單。

測試 SPF 是否生效

配置之後,我們測一下 SPF 是否真的生效, 同樣用 emkei.cz 這個站點傳送一封欺詐郵件到 gmail ,這時候可以看到收到了:

png

郵件收到了,但是好像跟沒有配置沒啥差別??? 其實不然,我們開啟 顯示原始郵件 看下

png

發現端倪了,郵件傳送源(emkei.cz)的 ip 地址是 93.99.104.21, 然後 gmail 郵件接收端通過 SPF 去查詢我們站點域名的 SPF 配置,發現這個 ip 不存在 _spf.google.comamazonses.com 旗下的所有的 ip 中。所以 SPF 就校驗失敗了。 而對於 gmail 郵件接收端來說, 如果 SPF 驗證失敗,就會提示一個問號, 表示 gmail 無法驗證郵件的正確來源,使用者要謹慎。

理解 “all” 在SPF中的設定

SPF有多種不同的設定,98%的域名使用 ~all (softfail),意思是如果spf條目與源郵件伺服器不對應,標識郵件為軟失敗。下表將展示SPF中 all 的區別:

引數 結果 含義
+all pass Permits all the email, like have nothing configured.(允許所有郵件,相當於未設定)
-all fail Will only mark the email like pass if the source Email Server fits exactly, IP, MX, etc. with the SPF entry.(僅通過匹配spf中正確配置IP、MX、etc.)
~all softfail Allows to send the email, and if something is wrong will mark it like softfail.(有錯誤的標識為軟失敗)
?all neutral Without policy(策略之外)

而我們設定的就是直接設定為失敗的 -all

檢測 SPF 是否正確

配置完之後,我們也可以通過一些外部工具站點來檢測我們的 SPF 配置是否正常:tools.wordtothewise.com/spf 這個站點將顯示所有能使用域名傳送的ip的概述

png

也就是說如果發件方的來源的 ip,不在這些 ip 列表裡面。那麼 SPF 檢測就會通不了。就會變成 FAIL。

DKIM 設定

雖然我們設定了 SPF, 但是結果也看到了,雖然在郵件詳情中,標記了 Fail, 但是使用者還是收到了,並且在正常的收件箱裡面,只不過旁邊多了一個問號提示 (其實上不同郵件接收端的針對 SPF 驗證fail 的處理方式不一樣,有些是放到垃圾箱中), 但是這個對於有些粗心的使用者還是會被騙。 所以我們有必要再加強身份驗證這一塊。也就有了 DKIM 的設定。

DKIM 概念

DKIM 域名金鑰識別郵件標準(Domain Keys Identified Mail)是一種通過檢查來自某域簽名的郵件標頭來判斷訊息是否存在欺騙或篡改的檢測電子郵件欺詐技術。

DKIM 是利用加密簽名和驗證的原理, 在發件人傳送郵件時候, 將與域名相關的私鑰加密的簽名欄位插入到訊息頭, 收件人收到郵件後通過DNS檢索發件人的公鑰(DNS TXT記錄), 就可以對簽名進行驗證, 判斷髮件人地址及訊息的真實性. 需要注意的是, DKIM 只能驗證發件人地址來源的真偽, 無法辨識郵件內容的真實性. 同時, 如果接收到無效或缺少加密簽名的訊息, DKIM 無法指定收件人採取什麼措施. 此外, 私鑰簽名是對本域所有外發郵件進行普遍的簽名, 是郵件中繼伺服器對郵件進行 DKIM 簽名而不是真正的郵件傳送人, 這意味著, DKIM 並不提供真正的端對端的電子簽名認證。

簡單的來說,就是使用 DKIM 傳送的電子郵件包括一個 DKIM-Signature 標頭欄位,該欄位包含郵件的加密簽名表示形式 (裡面有私鑰)。接收郵件的提供商可以使用公有金鑰(這在發件人的 DNS 記錄中發現)對簽名進行解碼。然後,電子郵件提供商使用此資訊來確定郵件是否是真實的。

舉個例子, 比如我們正常的 gmail 或ses 傳送郵件時,通過和域關聯,自動生成的私鑰加密郵件,生成DKIM-Signature簽名,然後將DKIM-Signature簽名及相關資訊插入到郵件標頭,傳送給接收方, 而接收方收郵件時,通過DNS 查詢獲得公鑰,驗證郵件DKIM簽名的有效性,從而確認在郵件傳送的過程中,防止郵件被篡改,保證郵件內容的完整性。所以只要能用找到的公鑰,去解標頭欄位裡面的私鑰資訊,就說明是真實的,其實就是非對稱的端對端加密,只不過我們把公鑰暴露在域名的 DNS TXT記錄中,接收郵件的提供商可以在公網上查到。 下面這張圖可以解釋這個過程:

png

DKIM 設定

設定其實就是在 DNS TXT 設定公鑰,因為我們用有用 aws ses 服務和 gmail, 所以要設定兩種:

SES DKIM 設定

通過 在 Amazon SES 中使用 DKIM 對電子郵件進行身份驗證 我們可以用最簡單的方式,就是 SES 提供的 Easy DKIM, 簡單來說,就是在已經驗證過的域名的配置那邊,點選生成 DKIM 的相關配置,這時候就會生成 3 條 cname 記錄,然後把這三條 cname 記錄放到 router 53 中就行了, 具體教程 為域設定 Easy DKIM

png

png

這樣子 SES 的 DKIM 就配置好了。

Gmail DKIM 配置

接下來我們配置 Gmail 的,Gmail 預設會有預設的DKIM設定,但是官方建議使用自己的域名,目前 Gmail 也是通過我們自己的域名做的驗證,直接一行 TXT 記錄:

png

其中 p 欄位後面就是一大段的公鑰。 這一大串也是自動生成的,就在 gmail 後臺:

  1. admin.google.com用你的Google App賬號登陸進入後臺,選擇Google AppGmailAuthenticate email。選擇你的域名生成公鑰。如下圖

png

  1. 按照生成的資訊,去你的 DNS 新增一條 TXT 記錄。
  2. 回到admin.google.com上次的頁面點選 “Start Authentication”。

這樣就生成了公鑰,並且生效了。

測試 DKIM 是否生效

一樣傳送一封正常的郵件到我的郵箱,如果 DKIM 有設定,並且成功的話,再郵箱詳情中就會出現 PASS

png

以上截圖說明我們有設定 DKIM,並且通過正確源傳送的郵件 DKIM 的校驗是正常的。

png

如果是冒充的,那麼就不會是 PASS,而是 FAIL。

而且這邊要注意一個細節的就是: 所有 DKIM 金鑰儲存在一個子域,命名為“_domainkey”。

上面截圖中,給定DKIM簽名欄位 d=xxx.com,s=google,DNS查詢為:google.domainkey.xxx.com (或者是 ses 對應的 domainkey 域名),google.domainkey.xxx.com 這條 txt 記錄會在我們 route 53 完成解析, 通過郵件表頭,通過DNS查詢公鑰資訊,如果和傳送郵件的私鑰進行匹配,通過了,那可能就不是垃圾郵件,沒有通過,那郵件有可能是垃圾郵件,或郵件內容被篡改了。

DMARC 設定

一般來講,通過設定 SPF 和 DKIM,可以有效的阻擋偽造郵件了,但是,因為不同的郵件廠商,處理垃圾郵件的策略不同,會存在一定的風險,比如,一封偽造郵件,騰訊和網易處理的方式,可能是直接拒絕,而 gmail 通常還是會正常進入信箱,只不過會通過 ?提示,因為無法確定郵件來源。 這樣的話,風險提示容易被忽視,會有極大的隱患,導致部分使用者被欺騙,考慮到我們大多數使用者對 gmail 的使用範圍,這個問題還是要徹底解決,通過進一步瞭解郵件服務安全設定問題,發現 DMARC 恰好能解決我們的問題,我們期望最終的效果就是,偽造郵件為通過驗證後,進入垃圾箱或直接拒收。

也就是之前哪怕我們設定了 SPF 和 DKIM, 但是不通過的郵件,可能因為不同的郵件廠商的關係,有可能是留在垃圾箱,也有可能留在收件箱,只不過帶有問號。這個還是有一定的風險的。所以我們需要一種策略來告訴郵件接收端,如果收到偽造郵件,直接按照我指定的策略走。不要根據你們自己的喜好來走。這個就是 DMARC 設定。

DMARC 概念

SPF 和 DKIM 中共同存在的問題是缺少有效的策略和反饋機制, 這兩個協議並未定義如何處理來自聲稱為某域的未經身份驗證的電子郵件, 如何處理第三方聲稱託管的某域的未經身份驗證的郵件, 如何反饋和統計聲稱是某域的身份認證成功或失敗的電子郵件。

DMARC 以域名為基礎的郵件認證、報告和一致性標準(Domain-based Message Authentication, Reporting, and Conformance) 就是用來解決 SPF 和 DKIM 中存在的這些問題, DMARC 的主要用途在於設定“策略”, 這個策略包含接收到來自某個域未通過身份驗證的郵件時應執行什麼操作、該域授權的第三方提供商傳送了未經身份驗證的郵件時該如何處理. DMARC 還會讓 ISP 傳送有關某個域身份驗證成功或失敗的報告, 這些報告將傳送至“rua”(彙總報告)和“ruf”(取證報告)中定義的地址中. 同時, DMARC 依靠出站郵件流配置的 SPF 記錄和 DKIM 金鑰來確保郵件來源及簽名的完整性, 當未通過 SPF 或 DKIM 檢查的郵件時便會觸發 DMARC 策略。

下面這張圖可以說明這個過程:

png

DMARC 常用引數

DMARC 配置的常用引數如下:

  • adkim:(純文字;可選的;預設為“r”)表明域名所有者要求使用嚴格的或者寬鬆的DKIM身份校驗模式,有效值如下:
r: relaxed mode
s: strict mode
複製程式碼
  • aspf:(純文字;可選的;預設為“r”)表明域名所有者要求使用嚴格的或者寬鬆的SPF身份校驗模式,有效值如下:
r: relaxed mode
s: strict mode
複製程式碼
  • fo:故障報告選項(純文字;可選的;預設為0),以冒號分隔的列表,如果沒有指定“ruf”,那麼該標籤的內容將被忽略。
    • 0:如果所有身份驗證機制都不能產生“pass”結果,那麼生成一份 DMARC 故障報告;
    • 1:如果任一身份驗證機制產生“pass”以外的結果,那麼生成一份 DMARC 故障報告;
    • d:如果訊息的簽名驗證失敗,那麼生成一份 DKIM 故障報告;
    • s:如果訊息的 SPF 驗證失敗,那麼生成一份SPF故障報告。
  • p:要求的郵件接收者策略(純文字;必要的)表明接收者根據域名所有者的要求制定的策略。
    • none:域名所有者要求不採取特定措施
    • quarantine:域名所有者希望郵件接收者將 DMARC 驗證失敗的郵件標記為可疑的。
    • reject:域名所有者希望郵件接收者將 DMARC 驗證失敗的郵件拒絕。
  • pct:(純文字0-100的整型;可選的,預設為100)域名所有者郵件流中應用DMARC策略的訊息百分比。
  • rf:用於訊息具體故障報告的格式(冒號分隔的純文字列表;可選的;預設為“afrf”)
  • ri:彙總報告之間要求的間隔(純文字32位無符號整型;可選的;預設為86400).表明要求接收者生成彙總報告的間隔不超過要求的秒數。
  • rua:傳送綜合反饋的郵件地址(逗號分隔的 DMARC URI純文字列表;可選的)
  • ruf:傳送訊息詳細故障資訊的郵件地址(逗號分隔的DMARC URI純文字列表;可選的)
  • sp:要求郵件接收者對所有子域使用的策略(純文字;可選的),若預設,則“p”指定的策略將應用到該域名和子域中。
  • v:版本(純文字;必要的)值為“DMARC1”,必須作為第一個標籤。

DMARC 配置

我們站點的具體配置一樣在 router 53 上配置(google 和 ses 的配置都一樣,所以只要統一配置一條即可), SES 有提供了具體的配置 使用 Amazon SES 遵守 DMARC, 比如這個:

"v=DMARC1;p=quarantine;pct=25;rua=mailto:dmarcreports@example.com"
複製程式碼

簡單地說,此策略告知電子郵件提供商執行以下操作:

  • 查詢“From”域為 example.com 且未通過 SPF 或 DKIM 身份驗證的所有電子郵件。
  • 將 25% 的未通過身份驗證的電子郵件傳送到垃圾郵件資料夾來進行隔離(您也可以使用 p=none 不採取任何操作;或使用 p=reject 直接拒收郵件)。
  • 在摘要中傳送有關未通過身份驗證的所有電子郵件的報告(即,在特定時間段內彙總資料的報告,而不是為每個事件傳送單獨的報告)。電子郵件提供商通常每天傳送一次此類彙總報告,但具體政策因提供商而異。

所以我們具體的配置如下:

_dmarc.xxx.com.
複製程式碼
"v=DMARC1;p=reject;rua=mailto:dmarc-reports@xxx.com; adkim=s;aspf=s"
複製程式碼

png

表示會執行以下操作:

  • 嚴格要求 SPF 和 DKIM 的身份驗證
  • 一旦驗證失敗,那麼將拒絕接收
  • 拒絕之後,傳送反饋到指定的郵箱

如果要檢視你的 SPF 和 DKIM 是否有遵守 DMARC, 可以通過指令來檢視:

nslookup -type=TXT _dmarc.xxx.com
複製程式碼

png

可以看到是沒問題的。 當然如果不會配置 DMARC 的話,這邊有個配置助手 可以幫助你配置:

png

DMARC 測試效果

放垃圾箱

既然配置好了,那麼接下來就可以測試了,加上我們將策略改成放入垃圾箱 (p=quarantine),這時候通過 emkei.cz 傳送的郵件,當 SPF 沒有通過的時候,就會放入垃圾箱

png

拒絕接收

如果改為拒絕的話 (p=reject), 直接拒絕郵件,並每天傳送退回郵件到發件箱,這裡說下,比如 hacker 仿造了一封郵件發給使用者,被拒絕了,那我們的正常的郵箱,比如support 會收到退信報告:

png

正常

如果正常的話, 就會三個策略都會 PASS, 因為我們有兩個傳送源,所以兩個都要試下

  1. 這個是 ses 的 no-reply 系列郵件

png

  1. 這個是 gmail 的 support 系列郵件

png

可以看到郵件 id 是不一樣的,一個是 ses, 一個是 gmail

DMARC 測試 SPF 和 DKIM 是否正常

我們知道在配置 DMARC 的時候, SPF 和 DKIM 一定要配好。雖然可以通過 nslookup。 但是也可以通過 外部的一些 第三方的站點來判斷,比如這個 DMARC Record Checker, 輸入你的域名,就可以檢查你的 DMARC 是否配置正常。

png

總結

通過 SPF + DKIM + DMARC, 我們的站點可以很好的解決電子郵件欺詐的問題了。

最後感謝樹禮的測試和對應的測試資料。 更多好文請看我的部落格:kebingzao.com/

參考資料

SPF 的測試工具

DKIM 的測試工具

  • dkimvalidator.com/ (你需要傳送一封郵件,如果測試通過,當你有DKIM配置,你將可以在網站上檢視到DKIM部分的返回結果)
  • dkimcore.org/tools/keych… (填寫selector 和域名進行檢查,可以對是否正確設定 DKIM 程式檢查)
  • www.hhlink.com/檢測DKIM/1 (通過給他傳送一封郵件,他可以幫你驗證 SPF 和 DKIM 是否正確)

DMARC 的測試工具

偽造郵件傳送測試站點

  • emkei.cz/ (傳送各種各樣的冒牌郵件)
  • tool.chacuo.net/mailanonymo… (偽造郵件、任意發件人傳送Email郵件、偽造郵件地址傳送電子郵件、任意郵件地址傳送電子郵件)

相關文章