DNSpooq系列漏洞分析與復現
發布時間 2021-02-01前言
近期,以色列安全咨詢企業JSOF在最新報告中披露了七個 DNSmasq 漏洞(統稱 DNSpooq),并指出攻擊者借此感染了數以百萬計的設備。DNSmasq 是一套流行的開源 DNS 轉發軟件,能夠為運行該軟件的網絡設備添加 DNS 緩存和 DHCP 服務器功能,廣泛用于各種小型局域網絡。受 DNSpooq 影響的設備不僅可能遭遇 DNS 緩存中毒,還可被用于遠程代碼執行、拒絕服務(DoS)攻擊。目前受影響的廠商包括但不限于 Android / Google、康卡斯特、思科、紅帽、Netgear、高通、Linksys、IBM、D-Link以及 Ubiquiti 。根據shodan顯示,有超100萬臺應用DNSmasq的設備暴露在公網,可能受影響的設備不計其數。
其中, CVE-2020-25684、CVE-2020-25685 和 CVE-2020-25686 這三個漏洞,可能導致 DNS 服務遭遇緩存中毒攻擊。另外四個漏洞為 CVE-2020-25687、CVE-2020-25683、CVE-2020-25682 和 CVE-2020-25681 ,均為緩沖區溢出漏洞。黑客或可在配置了 DNSmasq 的網絡設備上,利用這些漏洞遠程執行任意代碼。
DNS協議簡介
DNS的請求和響應的基本單位是DNS報文(Message)。請求和響應的DNS報文結構是完全相同的,每個報文都由以下五段(Section)構成:
DNS Header是每個DNS報文都必須擁有的一部分,它的長度固定為12個字節。Question部分存放的是向服務器查詢的域名數據,一般情況下它只有一條Entry。每個Entry的格式是相同的,如下所示:
QNAME:由labels序列構成的域名。QNAME的格式使用DNS標準名稱表示法。這個字段是變長的,因此有可能出現奇數個字節,但不進行補齊。DNS使用一種標準格式對域名進行編碼。它由一系列的label(和域名中用.分割的label不同)構成。每個label首字節的高兩位用于表示label的類型。RFC1035中分配了四個里面的兩個,分別是:00表示的普通label,11(0xC0)表示的壓縮label。
Answer,Authority和Additional三個段的格式是完全相同的,都是由零至多條Resource Record(資源記錄)構成。這些資源記錄因為不同的用途而被分開存放。Answer對應查詢請求中的Question,Question中的請求查詢結果會在Answer中給出,如果一個響應報文的Answer為空,說明這次查詢沒有直接獲得結果。
RR(ResourceRecord)資源記錄是DNS系統中非常重要的一部分,它擁有一個變長的結構,具體格式如下:
● NAME:它指定該條記錄對應的是哪個域名,格式使用DNS標準名稱表示法
● TYPE:資源記錄的類型。
● CLASS:對應Question的QCLASS,指定請求的類型,常用值為IN,值為0x001。
● TTL(Time To Live)資源的有效期:表示你可以將該條RR緩存TLL秒,TTL為0表示該RR不能被緩存。TTL是一個4字節有符號數,但是只使用它大于等于0的部分。
● RDLENGTH:一個兩字節非負整數,用于指定RDATA部分的長度(字節數)。
● RDATA:表示一個長度和結構都可變的字段,它的具體結構取決于TYPE字段指定的資源類型。
DNS常見資源記錄類型有NS記錄、A記錄、CNAME記錄。
● NS記錄
NS記錄用于指定某個域的權威DNS。比如在com的DNS里,記錄著http://baidu.com這個域的DNS,大概如下:
baidu.com. NS ns1.baidu.com.
baidu.com. NS ns2.baidu.com.
baidu.com. NS ns3.baidu.com.
這三條記錄,就是說http://ns1.baidu.com、http://ns2.baidu.com、http://ns3.baidu.com(以下簡稱ns1、ns2、ns3)都是http://baidu.com域的權威DNS,詢問任意其中一個都可以。
當然,在com的權威DNS里,還會記錄ns1~ns3這幾個http://baidu.com權威DNS的IP,會一并返回給問詢者,以便問詢者直接用IP聯系ns1~ns3。
● A記錄
A記錄就是最經典的域名和IP的對應,在http://ns1.baidu.com里面,記錄著百度公司各產品的域名和IP的對應關系,每一個這樣的記錄,就是一個A記錄,比如下面的3個A記錄:
image.baidu.com A 1.2.3.4
wenku.baidu.com A 5.6.7.8
tieba.baidu.com A 9.10.11.12
如果用戶詢問http://ns1.baidu.com:“http://wenku.baidu.com的IP是多少?”,ns1就會找到對應的A記錄或者CNAME記錄并返回。
● CNAME記錄
CNAME記錄也稱別名記錄,允許將多個記錄映射到同一臺計算機上。比如,在ns1中,并沒有http://www.baidu.com的A記錄,而是一個CNAME記錄:
www.baidu.com CNAME www.a.shifen.com
也就是告訴用戶,http://www.baidu.com的別名是http://www.a.shifen.com,可以直接請求解析http://www.a.shifen.com。
DNS緩存攻擊
當訪問www.baidu.com時,域名解析的大致流程如下圖所示。
DNS緩存中毒是一種比較經典的攻擊方式,如果攻擊者可以成功執行,就會在DNS緩存服務器上留下一個有害的條目,使得用戶訪問正常網站的請求重定向到被攻擊者控制的惡意網站。
DNSpooq系列緩存中毒漏洞的簡單攻擊流程圖如下圖所示:
(1)用戶發送瀏覽淘寶的請求給DNS轉發器,希望得到對應的IP。
(2)DNS轉發器沒有此域名的緩存,所以將請求轉發給上游DNS服務器。
(3)在得到上游DNS服務器回復前,攻擊者發送一個偽造的回復,將淘寶域名與一個惡意IP相對應。
(4)DNS轉發器接受了這個偽造的回復,并發送給用戶,于是用戶請求訪問的淘寶被重定向到了攻擊者操縱的惡意網站。
這個DNS轉發器應用場景很廣泛,比如個人開的熱點,機場、賓館里的公共網絡等,一旦攻擊成功,則影響使用這些網絡的所有人。
在DNS Header中有一個16-bit的區域叫TXID(transaction ID),用于將查詢包和回復包匹配。在過去,TXID是防御DNS緩存中毒的重要手段。但是在2008年,安全研究員Dan Kaminsky證明16-bit的TXID是遠遠不夠的,后來又增加了端口隨機化,所以這個時候想偽造回復包,不僅需要猜對TXID,還需要猜對端口,一共32位的隨機值,此外還需要知道源IP和目的IP。
DNS安全擴展
到了21世紀,DNS安全擴展正在被慢慢應用。DNS安全擴展是目前為了解決DNS欺騙和緩存污染問題而設計的一種安全機制。DNSSEC依靠數字簽名來保證DNS應答報文的真實性和完整性。簡單來說,權威服務器使用私鑰對資源記錄進行簽名,遞歸服務器利用權威服務器的公鑰對應答報文進行驗證。如果驗證失敗,則說明這一報文可能是有問題的。
為了實現資源記錄的簽名和驗證,DNSSEC增加了四種類型的資源記錄:RRSIG(Resource Record Signature)、DNSKEY(DNS Public Key)、DS(Delegation Signer)、NSEC(Next Secure)。
例如我們執行命令行:dig @8.8.8.8 paypal.com,得到的DNS查詢結果如下所示:
紅框中為應答部分,這是未開啟DNSSEC的情況下的。我們執行命令行:dig+dnssec @8.8.8.8 paypal.com,得到的DNS查詢結果如下所示:
藍框中便是RRSIG資源記錄存儲,該資源記錄存儲的是對資源記錄集合(RRSets)的數字簽名。
Dnsmasq緩存中毒漏洞
以下三個漏洞,組合起來用可以降低偽造回復包的熵值。
● CVE-2020-25684
DNSmasq本身限制了轉發給上游服務器查詢包的數量,通常最大是150條。用戶可以自己設定這個值。轉發查詢使用的是frec(forwardrecord)結構。每個frec都和TXID相關聯。當回復被接受或經過一定時間,這個frecs就會被刪除。
通常情況下,用于轉發查詢的socket數量被限制在64個。每個用于轉發的socket和一個隨機的端口綁定。
理論上,查詢包中TXID和源端口加起來會有32-bit的熵。但是實際上,這個熵要更少一些。因為dnsmasq在同一個端口會多路復用多個TXID,而沒有將每個TXID和每個端口設置為一一對應的關系,如下圖所示。結果就是,攻擊者只需要猜中64個端口中的一個端口還有正確的TXID就可以了,而不用猜中某個特定的端口和特定的TXID。所以這導致實際上只有26位熵值。
● CVE-2020-25685
如果要對DNS轉發器進行投毒,除了需要猜對正確的TXID和源端口,攻擊者發送偽造的回復還需要匹配已開放的frecs。如果想讓frec匹配,那么TXID和問題區都要匹配,換句話說,回復的內容是之前詢問過的。
dnsmasq只存放問題區的哈希值,而不是把整個語句存下來。當整個查詢提交的時候,這個哈希值會被保存。
如果dnsmasq沒有編譯DNSSEC支持,那么他默認使用CRC32作為哈希算法。問題就在于CRC32從密碼學角度并不是一個安全的算法??梢院茌p松的使用類似SMT solver等工具進行CRC32碰撞,這里原理不做過多介紹。
所以基于這一特性,攻擊者可以生成多個查詢,每一個查詢的CRC32的值都相同,不過查詢的是不同的域名,而這些域名最好是不存在的,即沒有被緩存的。然后攻擊者可以發送一個具有相同CRC32值的偽造的回復。
如下圖所示,攻擊者控制一臺客戶端對多個域名發起問詢,每一個CRC32的值都是相同的,然后在遞歸DNS服務器回復之前,回復一個具有相同CRC32值的域名或IP,攻擊即有可能成功。
● CVE-2020-25686
dnsmasq的另一個問題就是在同一個域名被查詢請求時會粗暴的創建多個frecs。隨后會轉發所有的請求,如果成功的匹配其中的任意一個,就計入緩存。這個問題導致就算dnsmasq使用安全的哈希算法,也可能成功的實施攻擊。
通過以上三個漏洞,導致攻擊者偽造惡意回復包的成功率大大提高,后面還需要利用dnsmasq沒有對回復包做驗證的特性進行攻擊。
一般情況下,在遞歸服務器上會對回復包做一些驗證機制,例如bailiwicks。但是在配置dnsmasq的設備上并沒有做任何驗證,所以可以在用戶請求www.example.com的時候,攻擊者可以發送如下回復:
www.example.com CNAME www.bank.com
www.bank.com A 6.6.6.6
然后這條記錄的緩存就會被插入到dnsmasq的設備中。前文介紹過CNAME,所以當用戶想訪問www.bank.com的時候,會被重定向到被攻擊者控制的IP為6.6.6.6的服務器。而配置了類似bailiwicks的設備,會去找權威服務器詢問www.bank.com的IP。
Dnsmasq緩沖區溢出漏洞
● CVE-2020-25681
以下名稱以規范的DNS名稱順序排序。最重要的標簽是“example”。在此級別上,“example”將首先排序,然后是以“a.example”結尾的名稱,然后是以“z.example”結尾的名稱。每個級別中的名稱以相同的方式排序。如下圖所示。
CVE-2020-25681漏洞位于dnssec.c文件的sort_rrset()函數中,該函數負責按照DNSSEC驗證過程的要求采用冒泡排序算法將給定的資源記錄集合(RRSets)排序為規范順序。該函數定義如下:
它接受了響應數據包(header)以及數據包長度(plen)。rrset是指向資源記錄集合中RR數組的指針,而rrsetidx是集合中的RR數,rr_desc是指向與RRset關聯的RR類型的描述符的指針。最后,有兩個緩沖區buff1和buff2,它們用作排序例程的工作區緩沖區。這兩個緩沖區在程序開始時都是相對分配的,它們是daemon> workspacename和daemon-> keyname。當dnsmasq開啟DNSSEC時,將會分配這兩個緩沖區。
MAXDNAME大小為1025,所以workspacename和keyname的大小2050,也是該漏洞發生溢出的緩沖區。
首先啟動dnsmasq,并設置參數為:
-p 53535 --no-daemon --log-queries -S127.0.0.2 --no-hosts --no-resolv -d -q --dnssec--trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D,構造完惡意DNS查詢響應包,使用命令行:dig NS+dnssec @localhost -p 53535 .,命中sort_rrset()函數斷點后如下圖所示:
在構造資源記錄集合(RRSets)時,必須保證記錄個數大于1,這樣才能保證進入排序循環。
這里構造的rrsetidx為0x3。
正常數據包如下圖所示:
Answers塊中,p1指向第一個資源記錄,p2指向第二個,然后進行排序。
分別跳過Class,Type和TTL,到達RDATA區域。
Data lengh為20,為Name Server的長度。然后進入排序循環。
行315,首先調用get_rdata()函數解析第一個資源記錄p1的RDATA域中的NameServer,看下該函數實現。
判斷d是否等于-1,這里不等于,不進入if語句,來到如下代碼。
然后調用extract_name()函數解析,這里需要保證extract_name()函數解析錯誤返回0,保證進入get_rdata()函數返回為0,通過設置超長NameServer字符串即可。
進入if語句,行318,計算len1,為end1-p1,即是NameServer的長度。行319,調用memcpy()將p1拷貝到buff1+left1中。
這里len1設置為3550,p1為NameServer,長度RDLENGTH為用戶可控。前文已經介紹buff1為daemon>workspacename,大小為2020,因此發生堆溢出。
緩解措施
● 升級dnsmasq到最新版本(2.83及以上),這是目前最有效的方法。
● 如果不必要,配置dnsmasq設備不要在WAN口監聽。
● 盡量配置dnsmasq最大轉發查詢條目小一點。
● 暫時關閉DNSSEC驗證選項。
● 使用為DNS提供傳輸安全的協議,如DoT或DoH。
參考鏈接:
[1] https://www.jsof-tech.com/disclosures/dnspooq/
[2] https://www.jsof-tech.com/wp-content/uploads/2021/01/DNSpooq-Technical-WP.pdf
[3] https://www.rfc-editor.org/rfc/rfc1664.txt
[4] https://security.googleblog.com/2017/10/behind-masq-yet-more-dns-and-dhcp.html
[5] https://spoofer.caida.org/summary.php
[6] https://www.rfc-editor.org/rfc/rfc7858.txt
[7] https://www.rfc-editor.org/rfc/rfc5452.txt
[8] http://www.thekelleys.org.uk/dnsmasq/doc.html
[9]https://dl.acm.org/doi/10.1145/3372297.3417280
[10] https://github.com/Z3Prover/z3
[11] https://www.chromium.org/developers/design-documents/dns-prefetching
[12] https://www.rfc-editor.org/rfc/rfc4033.txt
[13] https://zhuanlan.zhihu.com/p/92899876
啟明星辰積極防御實驗室(ADLab)
ADLab成立于1999年,是中國安全行業最早成立的攻防技術研究實驗室之一,微軟MAPP計劃核心成員,“黑雀攻擊”概念首推者。截止目前,ADLab已通過CVE累計發布安全漏洞近1100個,通過 CNVD/CNNVD累計發布安全漏洞1000余個,持續保持國際網絡安全領域一流水準。實驗室研究方向涵蓋操作系統與應用系統安全研究、智能終端安全研究、物聯網智能設備安全研究、Web安全研究、工控系統安全研究、云安全研究。研究成果應用于產品核心技術研究、國家重點科技項目攻關、專業安全服務等。