1.概述
2022年5月,安全公司Malwarebytes在可能用于針對約旦政府的一份武器化文件中新發現了一個名為“Saitama”的惡意軟件樣本。Saitama植入軟件使用DNS隧道作為其唯一的命令和控制信道,并利用長時間睡眠和隨機化(子)域名來逃避檢測。這些特性使得即使植入程序不使用DNS over HTTPS(DoH)來加密其DNS查詢,也難以通過流量檢測到它。由于沒有該植入程序的服務器端實現,分析人員難以對此類惡意流量的檢測效果進行測試。
雖然某些入侵指標可用于追溯可能的感染,但分析人員更傾向(接近)實時地檢測威脅。為了評估和調整現有的惡意流量檢測覆蓋范圍,需要更詳細地了解植入程序的內部工作原理。本文將使用Saitama植入來說明惡意DNS隧道如何建立,以及這種方式如何影響檢測過程。
2.重建Saitama流量
??從受害者機器的角度來看,Saitama植入程序的行為已經在其他地方得到了記錄。然而,為了生成植入程序行為的完整記錄,需要一個C2服務器來正確控制和指示植入程序。當然,植入程序的實際開發人員使用的C2服務器的源代碼是無法使用的。
如果最終目標是實時檢測惡意軟件,則檢測工作應側重于植入程序產生流量的方式,而非流量發送到的特定域名。檢測方法依據的是PCAP包,通俗來說,即“要么產生PCAP,要么就當什么也沒發生”。因此,在構建檢測時,本文沒有依賴于假設,而是構建了Saitama的服務器端組件,以便能夠生成PCAP。
從攻擊者的角度來看,使用DNS作為C2通信的信道有一些好處,也有一些主要的缺點。雖然在許多環境中DNS確實相對不受限制,但協議本身并不是為傳輸大量數據而設計的。此外,DNS查詢的緩存特點迫使植入程序必須確保發送的每個DNS查詢都是唯一的,從而保證DNS查詢能夠到達C2服務器。
為此,Saitama植入程序依賴于對用于構造DNS查詢的字符集的連續打亂。雖然這種打亂使得兩個連續的DNS查詢幾乎不可能是相同的,但它需要服務器和客戶端完全同步,以便它們以相同的方式打亂字符集(見圖1)。
圖1:服務器端與客戶端打亂字母表采用相同的方式
在啟動時,Saitama植入程序生成一個介于0和46655之間的隨機數,并將其分配給一個計數器變量。客戶端使用共享密鑰(“haruto”用于此處討論的變體)和共享初始字符集(“razupgnv2w01eos4t38h7yqidxmkljc6b9f5”),對該計數器進行編碼,并通過DNS將其發送到C2服務器。然后將此計數器用作偽隨機數發生器(PRNG)的種子。
為了對該計數器進行編碼,植入程序依賴于名為“_IntToString”的函數(見圖2)。此函數接收一個整數和一個“基本字符串”,對于第一個DNS查詢,該字符串與上一段中標識的初始共享字符集相同。在整數變量等于或小于零之前,函數使用該整數變量從基本字符串中選擇一個字符,并將其放置到變量“str”之前,將拼接后的字符串作為函數輸出返回。在每次循環迭代結束時,輸入數除以基串參數的長度,從而降低整數變量的值。
圖2:用于將整數轉換為編碼字符串的函數
要確定初始種子,服務器必須執行此函數的逆運算,以將編碼字符串轉換回其原始數字。但是,在客戶端轉換過程中,由于此轉換中的除法并未保留小數,可能會導致信息的丟失。服務器嘗試使用簡單的乘法來完成此轉換的逆運算。因此,服務器可能會計算出一個不等于客戶端發送的種子的數字,此時必須驗證逆函數是否計算了正確的種子。如果不是這種情況,服務器會嘗試更高的數字,直到找到正確的種子。
一旦克服了這個障礙,服務器端實現的其余部分就變得微不足道了。客戶端將其當前計數器的值附加到發送到服務器的每個DNS查詢。此計數器用作偽隨機數發生器PRNG的種子。此PRNG用于將初始字符集打亂為新字符集,然后用于對客戶端發送到服務器的數據進行編碼。
因此,當服務器和客戶端使用相同的種子(計數器變量)來生成偽隨機數以打亂字符集時,會得到完全相同的字符集。這允許服務器和植入程序以相同的“語言”進行通信。然后,服務器簡單地將打亂后的字母表中的字符替換回“基本”字母表,以獲得客戶端發送的數據。
3.植入程序規避檢測的方法??
許多C2框架允許攻擊者手動設置植入程序的最小和最大睡眠時間。雖然較少的睡眠時間使攻擊者能夠更快地執行命令和接收輸出,但較多的睡眠時間會在受害者網絡中產生較少的噪聲以規避檢測。流量檢測通常依賴于設定的一個閾值,可疑行為僅在特定時間內發生多次時才會觸發警報。
Saitama植入程序使用硬編碼睡眠值(見圖3)。在通信期間(例如當它將命令輸出返回到服務器時),最小睡眠時間為40秒,而最大睡眠時間為80秒。在發送的每個DNS查詢中,客戶端將選擇40到80秒之間的隨機值。此外,DNS查詢并不是每次都發送到同一個域名,而是分布在三個域名中。在每個請求中,隨機選擇其中一個域名。植入程序無法在運行時改變睡眠時間,也無法完全“跳過”睡眠步驟。
圖3: 植入程序的睡眠配置(整數表示以毫秒為單位的睡眠時間)
這些睡眠時間和通信分布阻礙了檢測工作,因為它們允許植入程序進一步“融入”合法的網絡流量。雖然對于經驗豐富的研究人員來說,流量本身并不是正常的,但睡眠時間和分布使得捕獲這種惡意流量無異于大海撈針。對于攻擊者來說,選擇睡眠時間值是在保持植入程序隱蔽性和可用性之間的平衡。對于Saitama的睡眠時間,由于每個單獨的DNS查詢只傳輸15字節的輸出數據,故植入程序的可用性非常低。
圖4:服務器實現和植入程序之間的傳輸
植入程序包含一組硬編碼命令,這些命令只能使用一個命令代碼觸發,而不是將整個命令從服務器發送到客戶端。然而,由于無法知道這些硬編碼命令是否被攻擊者使用,或者作為誤導手段留在植入程序中,歸因與溯源受到了嚴重阻礙。此外,這些硬編碼命令的輸出仍然必須以與任何其他發送命令相同的延遲發送回C2服務器。
4.檢測DNS植入程序的方法
檢測DNS隧道一直是研究的重點,因為這種技術可以以多種不同的方式實現。此外,通信信道的復雜性迫使攻擊者制造更多噪音,因為他們必須通過非專用信道發送大量數據。雖然“空閑”植入程序可能很難檢測到,因為很少通過有線介質進行通信,但任何DNS植入程序在開始接收命令和發送命令輸出時都必須發出更多噪聲。這些“突發”通信是可以更好地檢測DNS隧道的地方。本節將舉例說明檢測Saitama的方法和實際上對手使用的一些常見工具。
(1)基于簽名
在可能的情況下,本文的目標是編寫基于簽名的檢測,因為這種檢測方法提供了堅實的基礎和快速的工具溯源。如前所述,Saitama植入程序使用的隨機化域名使得基于特征的檢測在這種情況下具有挑戰性,但并非不可能。當主動傳送命令輸出時,Saitama植入程序生成大量隨機DNS查詢。這種隨機化確實遵循一種特定的模式,可以用以下Suricata規則來概括:
alert dns $HOME_NET any -> any 53 (msg:”FOX-SRT – Trojan – Possible Saitama Exfil Pattern Observed”; flow:stateless; content:”|00 01 00 00 00 00 00 00|”; byte_test:1,>=,0x1c,0,relative; fast_pattern; byte_test:1,<=,0x1f,0,relative; dns_query; content:”.”; content:”.”; distance:1; content:!”.”; distance:1; pcre:”/^(?=[0-9]+[a-z]\\|[a-z]+[0-9])[a-z0-9]{28,31}\\.[^.]+\\.[a-z]+$/”; threshold:type both,track by_src, count 50, seconds 3600;classtype:trojanActivity;priority:2;reference:url,https://github.com/fox-it/saitama-server metadata:ids suricata; sid:21004170; rev:1;)
此簽名可能看起來有點復雜,但如果將其分解為單獨的部分,則會變得相對直觀。28-31個字符的選擇基于包含輸出的DNS查詢的結構。首先,一個字節專用于“發送和接收”命令代碼。然后跟隨植入程序的編碼ID,該ID可以占用1到3個字節。緊接其后是2個字節專用于輸出數據的字節索引和20字節的base-32編碼輸出。最后,將發送“計數器”變量的當前值。由于該數字的范圍在0到46656之間,因此需要1到5個字節。Suricata IDS 規則的內容匹配如下表所示:
內容匹配 | 行為 |
00 01 00 00 00 00 00 00 | DNS查詢標頭。此匹配主要用于將指針放在byte_test內容匹配的正確位置。 |
byte_test:1,>=,0x1c,0,relative; | 下一個字節應至少為十進制 28。此字節表示即將到來的子域名的長度 |
byte_test:1,<=,0x1f,0,relative;< p=””> | 與前一個字節相同的字節最多應為 31。 |
dns_query; content:”.”; content:”.”; distance:1; content:!”.”; | DNS 查詢應正好包含兩個“.”字符 |
pcre:”/^(?=[0-9][a-z]|[a-z][0-9])[a-z0-9] {28,31}\\.[^.]\\.[a-z]$/”; | DNS 查詢中的子域名應至少包含一個數字和一個字母,并且不能包含其他類型的字符。 |
threshold:type both, track by_src, count 50, seconds 3600 | 僅當過去3600 秒中的查詢超過 50個時才觸發。并且每3600 秒僅觸發一次。 |
(2)基于行為
使創建簽名變得困難的隨機化域名也對防御者有利:大多數正常DNS 查詢并非隨機。如下表所示,列出的每個黑客工具都至少有一個子域名具有加密或編碼的部分。
黑客工具 | 舉例 |
DNScat2 | 35bc006955018b0021636f6d6d616e642073657373696f6e00.domain.tld |
Weasel | pj7gatv3j2iz-dvyverpewpnnu–ykuct3gtbqoop2smr3mkxqt4.ab.abdc.domain.tld |
Anchor | ueajx6snh6xick6iagmhvmbndj.domain.tld |
Cobalt Strike | Api.abcdefgh0.123456.dns.example.com 或 post. 4c6f72656d20697073756d20646f6c6f722073697420616d65742073756e74207175697320756c6c616d636f206420646f6c6f7220616c69717569702073756e7420636f6d6f646f20656975736d6f642070726.c123456.dns.example.com |
Sliver | 3eHUMj4LUA4HacKK2yuXew6ko1n45LnxZoeZDeJacUMT8ybuFciQ63AxVtjbmHD.fAh5MYs44zH8pWTugjdEQfrKNPeiN9SSXm7pFT5qvY43eJ9T4NyxFFPyuyMRDpx.GhAwhzJCgVsTn6w5C4aH8BeRjTrrvhq.domain.tld |
?Saitama | 6wcrrrry9i8t5b8fyfjrrlz9iw9arpcl.domain.tld |
遺憾的是,DNS查詢中的隨機性檢測本身并不是一個可靠的指標,無法在不產生大量誤報的情況下檢測DNS隧道。然而,DNS隧道的第二個限制是DNS查詢只能承載有限數量的字節。要成為有效的C2通道,攻擊者需要能夠發送多個命令并接收相應的輸出,從而導致較短時間內集中產生了大量的查詢。
這基于行為的檢測的第二步:簡單地計算被分類為“隨機化域名”的唯一查詢的數量。這些集中產生的大量查詢在細節上因使用工具而異,但一般來說,兩個查詢之間沒有空閑時間或空閑時間很少。而Saitama是一個例外,它在兩個查詢之間有40到80秒的均勻分布的睡眠時間,這意味著平均有一分鐘的延遲。60秒的預期睡眠是確定閾值的直觀開始。如果我們聚合超過一小時,預計平均將有60個查詢分布在3個域名上,在50%的情況下,一小時內的查詢少于60次。
圖5:模擬出的查詢操作的均勻隨機觀測值之和近似正態分布(1h)
為了確保檢測結果,無論隨機睡眠時間如何,都可以利用均勻隨機觀測值之和近似正態分布這一事實。通過這種分布計算出產生可接受概率的查詢數。如圖5所示,該值可取為53(此數字因檢測工具而異,并非內置閾值。不同工具的不同閾值可用于平衡誤報)。保險起見,為了涵蓋可能的數據包丟失和其他意外因素,在簽名和其他規則中此值可取為50。
總之,將對隨機出現的DNS查詢的檢測與每小時隨機類DNS查詢的最小閾值相結合,可以成為檢測DNS隧道的有效方法。分析人員在測試中發現仍然存在一些誤報,例如由防病毒解決方案引起的誤報。因此,最后還要為已驗證為正常的域名創建一個排除列表,以防止正常域名產生的誤報。
雖然還可以使用更復雜的檢測方法,但該方法已經足夠強大(至少足以捕獲該惡意軟件),更重要的是,該方法易于在網絡傳感器或SIEM等不同平臺以及各種類型的日志上使用。
5. 結論
當出現新的惡意軟件時,分析人員的核心工作應該在于確保現有的檢測工作在新遇到的威脅上能夠正確觸發。雖然某些入侵指標可用于追溯尋找可能的感染,但研究人員更傾向(接近)實時地檢測威脅。本文概述了作者如何開發植入程序的服務器端實現,以創建植入程序行為的正確記錄,最終用于檢測工程目的。
強隨機化(如在Saitama植入程序中觀察到的)顯著阻礙了基于簽名特征的檢測。本文通過檢測其規避方法(在本例中為隨機化)來檢測威脅。正常的DNS流量很少由隨機出現的子域名組成,當看到這種情況在以前看不到的域名中大量出現時,很可能是出現了惡意流量。
參考鏈接:https://blog.fox-it.com/2022/08/11/detecting-dns-implants-old-kitten-new-tricks-a-saitama-case-study/
來源:國家網絡威脅情報共享開放平臺