Windows DNS Server遠程代碼執(zhí)行漏洞分析
- CNNVD編號:未知
- 危害等級: 高危
- CVE編號:CVE-2020-1350
- 漏洞類型: 遠程代碼執(zhí)行
- 威脅類型:遠程
- 廠 商:未知
- 漏洞來源:深信服
- 發(fā)布時間:2021-01-06
- 更新時間:2021-01-13
漏洞簡介
Microsoft Windows Server操作系統(tǒng)自帶了一個DNS server,Windows自Windows 2000后提供了一些DNS API給應用程序開發(fā)者,允許他們通過這些API使用一些DNS方法(例如創(chuàng)建DNS查詢,比較記錄,查找name等)。
一種最簡單的用戶和DNS Server的交互過程如下圖所示:
DNS查詢和響應均通過DNS消息進行傳輸,消息的結(jié)構(gòu)如下所示:
+---------------------+
| Header |
+---------------------+
| Question / Zone | the question / zone for the name server
+---------------------+
| Answer / Prereq | RRs answering the question / prereq
+---------------------+
| Authority / Updates | RRs pointing toward an authority / updates
+---------------------+
| Additional | RRs holding additional information
+---------------------+
此外,DNS還包含Dynamic Update消息類型,在結(jié)構(gòu)上類似于query/response,但是在Dynamic Update消息中的section的名稱有一定變化,如上面結(jié)構(gòu)所示,Question稱為Zone,Answer稱為Prerequisites,Authority稱為Updates。
DNS Header部分的結(jié)構(gòu)如下所示:
Field | Length(Bits) | Description |
ID | 16 | 匹配query和response消息的ID |
QR | 1 | 指明為Query(QR=0)還是Response(QR=1)的flag標志 |
OPCODE | 4 | 指明query的類型,0表示為標準類型,5表示為Dynamic Update |
AA | 1 | Authoritative Answer,表明answer是否來自于authority |
TC | 1 | Truncation,指明是否因為傳輸限制進行truncate |
RD | 1 | Recursion Desired,指明resolver是否遞歸執(zhí)行query |
RA | 1 | Recurision Available,指明resolver是否遞歸處理query |
Z | 3 | 未使用 |
RCODE | 4 | 指明錯誤狀態(tài),0表示沒有錯誤 |
QDCOUNT | 16 | Question/Zone Section中的entity數(shù)量 |
ANCOUNT | 16 | Answer/Prereq Section中的entity數(shù)量 |
NSCOUNT | 16 | Authority/Updates Section中的entity數(shù)量 |
ARCOUNT | 16 | Additional Section中的entity數(shù)量 |
所有多字節(jié)數(shù)據(jù)均以大端序進行傳輸,上面提到的各個section都包含不定數(shù)量的Resource Records(RR),這些RR指定了DNS 資源和entity的詳細信息。RR的結(jié)構(gòu)如下:Field | Length(bytes) | Description |
Name | var | Owner Name,該domain屬于的node |
Type | 2 | 資源記錄type碼 |
Class | 2 | 資源記錄class碼 |
TTL | 4 | 記錄緩存的秒數(shù) |
RDLENGTH | 2 | RDATA字段的長度 |
RDATA | var | 記錄數(shù)據(jù),格式取決于type和class |
對于Zone section來說,包含如上格式的RR,但是省略TTL,RDLENGTH,RDATA。
Name字段編碼了0個或多個DNS標簽,標簽以空字符結(jié)尾。每個標簽為一個1字節(jié)固定長度的字節(jié)字符串。例如,一個域名為www.example.com,會切分成3個標簽,www,example以及com,然后進行編碼組合到一起\x03www\x07example\x03com\x00?;蛘?,不使用按照長度編碼為字節(jié)字符串,而是一個標簽包含一個2字節(jié)的指針,前2個最重要的位設置為1,其他位存儲從DNS Header部分的未壓縮標簽出現(xiàn)的位置的偏移(字節(jié)數(shù)),例如Zone包含一個Name為\x03www\x07example\x03com\x00的RR,然后其他的RR可以使用2字節(jié)的指針\xc0\xc0指向該name,0xc0是距Zone RR的Name字段出現(xiàn)的DNS數(shù)據(jù)包起點的偏移。
Dynamic Update是可以遠程更新DNS記錄的一種功能,該功能允許經(jīng)過授權(quán)的更新者區(qū)域中的權(quán)威名稱server上增加和刪除資源記錄。通常情況下,Dynamic Update使用SIG或者TSIG對更新進行簽名。
漏洞公示
在Windows系統(tǒng)中,DNS Client和DNS Server通過兩個不同的模塊進行實現(xiàn):
- DNS Client:dnsapi.dll,負責處理DNS 解析- DNS Server:dns.exe,負責響應DNS查詢在dns.exe中,實現(xiàn)針對各種支持的響應類型的解析函數(shù):
dns!RR_DispatchFunctionForType()通過RRWireReadTable來確定對應的處理功能。RRWireReadTable中包含的支持的響應類型如下:
對于SIG 查詢的響應類型也在其中。而處理 SIG 查詢的響應類型的函數(shù)為dns!SigWireRead(),其匯編代碼如下:
也就是在接收到包含SIG RRd的Dynamic Update查詢后,dns!SigWireRead()函數(shù)被調(diào)用來進行RR解析,并存儲到一個堆緩沖區(qū)中。在調(diào)用DNS!RR_AllocateEx()函數(shù)進行堆區(qū)分配之前,首先調(diào)用dns!Name_PacketNameToCountNameEx()函數(shù)統(tǒng)計Signer's Name的長度,然后按照如下公式進行計算需要分配的緩沖區(qū)的大?。?/section>bsize (buffer size) = Length of uncompressed Signer's Name + 0x14 + Length of Signature
上面公式的計算過程使用的均為16位寄存器,然后在RR_AllocateEx()函數(shù)中進行擴展:
如果最后bsize的計算結(jié)果大于0xFFFF(16位寄存器能表示的最大值),那么在傳入RR_AllocateEx()函數(shù)進行內(nèi)存分配操作時,就會分配一個很小的緩沖區(qū):
從代碼中可以看到,在進行內(nèi)存分配時,實際分配的內(nèi)存大小為bsize + 0x4a,而且在進行copy操作時,將SIG RR的Signature字段copy到了偏移為Length of uncompressed Signer's Name+0x4c處的緩沖區(qū)中,這主要是為了確保Signature可以被copy到緩沖區(qū)的末尾位置。
正常情況下,bsize的計算結(jié)果會比0xFFFF小,原因如下:- DNS通過TCP傳輸?shù)膒acket的最大數(shù)據(jù)量為0xFFFF- DNS的packet一定包含一個12字節(jié)的Header- 對于root zone來說,一個最小的Zone RR大小為5字節(jié)- Signer's Name字段前的SIG RR的長度為18個字節(jié)
因此,在正常情況下,Signer's Name和Signature長度的和一定小于0xFFFF - 12 - 5 - 18 = 0xFFDC,那么也就說明bsize的長度不會大于0xFFF0(0xFFDC + 0x14)。
但是,仍然有可能構(gòu)造一個惡意的Signer's Name來使得bsize的大小超過0xFFFF來造成溢出。因為SIG RR的前18個字節(jié)在調(diào)用memcpy()函數(shù)之前都不會被處理,從而可以任意使用這些字節(jié)來存儲一個DNS name,而且,構(gòu)造的DNS name的最后2個字節(jié)可以指向Zone RR的Name字段。例如,Name的前18個字節(jié)如下:\x0FAAAAAAAAAAAAAAA\xc0\x0c
使用嵌套指針在SIG RR的18個字節(jié)中構(gòu)造一個Name,如下所示:
Label1 = <Label1_Length> <Label1_Name> \xc0\x0c
Crafted_Name = <Label2_Length> <Label1> <Pointer1>
Pointer1指向Label1_Length處的字節(jié)。請注意,Crafted_Name包含一個指向Label1的指針Pointer1,Label1本身包含在Crafted_Name中。由于Label1的指向\xc0\x0c后綴(即Zone RR的Name字段),因此不會導致無限遞歸,而是通過添加作為名稱子集的后綴來延長Crafted_Name 。以一個例子來說明該種方案:Label1 = \x0cAAAAAAAAAAAA\xc0\x0c
Crafted_Name = \x11\x0cAAAAAAAAAAAA\xc0\x0c\xc0XX
其中,Zone假設為example.com,XX指向Label1。Crafted_Name就變成\x0CAAAAAAAAAAAA\xC0\x0C.AAAAAAAAAAAA.example.com,長度由原來的18字節(jié)變?yōu)?0字節(jié)。通過嵌套指針,使得長度變?yōu)榱嗽瓉淼?倍。如果Signer's Name指向Crafted_Name,那么就可能實現(xiàn)bsize大于0xFFFF,從而觸發(fā)漏洞。
補丁
1、微軟官方補丁
微軟官方目前已發(fā)布針對此漏洞的安全更新補丁,千里目實驗室建議廣大用戶及時確認所用Windows版本,并下載對應版本安全補丁進行更新:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350
微軟官方對于無法及時安裝安全更新的用戶提供了臨時的緩解措施:
通過注冊表編輯器,限制tcp包的長度
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters DWORD = TcpReceivePacketSize
Value = 0xFF00
注意:需要重新啟動DNS服務才能生效。
移除此臨時緩解措施:
管理員可以移除值 TcpReceivePacketSize 及其數(shù)據(jù),使注冊表項 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DNS\Parameters 下的所有其他內(nèi)容恢復原來的狀態(tài)。
【深信服下一代防火墻】
可輕松防御此漏洞,建議部署深信服下一代防火墻的用戶更新至最新的安全防護規(guī)則,可輕松抵御此高危風險。【深信服EDR】
深信服EDR已完成漏洞規(guī)則庫更新,支持該漏洞的檢測及補丁分發(fā)。EDR3.2.10及以上版本需要升級相應的SP包,更新漏洞補丁規(guī)則庫版本到20200722103111及以上版本,即可檢測漏洞并分發(fā)補丁進行漏洞修復。聯(lián)網(wǎng)用戶可直接在線更新,離線升級包及漏洞補丁規(guī)則庫已上傳至深信服社區(qū),有需要的用戶請到深信服社區(qū)下載。【深信服云盾】
已第一時間從云端自動更新防護規(guī)則,云盾用戶無需操作,即可輕松、快速防御此高危風險。【深信服安全感知平臺】
可檢測利用該漏洞的攻擊,實時告警,并可聯(lián)動【深信服下一代防火墻等產(chǎn)品】實現(xiàn)對攻擊者ip的封堵。【深信服安全運營服務】
深信服云端安全專家提供7*24小時持續(xù)的安全運營服務。在漏洞爆發(fā)之初,對存在漏洞的用戶,檢查并更新了客戶防護設備的策略,確??蛻舴雷o設備可以防御此漏洞風險。https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350