CVE-2020-16898 "Bad Neighbor " Windows TCP/IP遠(yuǎn)程代碼執(zhí)行漏洞分析
一、漏洞信息
1. 漏洞簡述
- 漏洞名稱:Windows TCP/IP Remote Code Execution Vulnerability
- 漏洞編號:CVE-2020-16898
- 漏洞類型:Design Weakness
- 漏洞影響:Code Execution
- CVSS評分:9.8
- 利用難度:Medium
- 基礎(chǔ)權(quán)限:不需要
2. 組件概述
TCP/IP是Internet上使用的通信協(xié)議。 在Windows的早期版本中,TCP/IP是一個單獨的可選組件,可以像其他任何協(xié)議一樣刪除或添加。從Windows XP/Server 2003開始,TCP/IP成為操作系統(tǒng)的核心組件,無法刪除。 將TCP/IP作為Windows的核心組件是非常有意義的,因為它的功能在Microsoft Windows Server上對網(wǎng)絡(luò)操作和Active Directory域環(huán)境尤為重要。 整個Active Directory架構(gòu)基于DNS層次結(jié)構(gòu),依賴于TCP/IP 傳輸協(xié)議 。
Microsoft Windows中的TCP/IP功能在內(nèi)核級別運行,并由驅(qū)動程序tcpip.sys提供。該驅(qū)動程序處理所有傳入和傳出的TCP/IP通信信息,包括解析從網(wǎng)絡(luò)接口接收到的數(shù)據(jù)包,以及解釋此數(shù)據(jù)并將其傳遞給更高級別的組件。
3. 漏洞利用
該漏洞主要是由于Windows TCP/IP堆棧在處理選項類型為25(0x19,遞歸DNS服務(wù)器選項)且長度字段值為偶數(shù)的ICMPv6的路由廣播數(shù)據(jù)包時,處理邏輯存在紕漏,導(dǎo)致存在遠(yuǎn)程代碼執(zhí)行漏洞。成功利用該漏洞的攻擊者可以在目標(biāo)機器(主機或服務(wù)器)上執(zhí)行任意代碼。
4. 漏洞影響
- Microsoft Windows 10 1709
- Microsoft Windows 10 1803
- Microsoft Windows 10 1809
- Microsoft Windows 10 1903
- Microsoft Windows 10 1909
- Microsoft Windows 10 2004
- Microsoft Windows Server 2019
- Microsoft Windows Server, version 1903
- Microsoft Windows Server, version 1909
- Microsoft Windows Server, version 2004
5. 解決方案
官方解決方案:微軟官方針對該漏洞已發(fā)布安全更新補丁,補丁地址:https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16898
臨時解決方案:
管理員啟動powershell或cmd,輸入以下命令檢查所有網(wǎng)絡(luò)IPv6接口的列表以及相應(yīng)的索引號:
netsh int ipv6 sh int
樣例輸出如下:
確認(rèn)網(wǎng)絡(luò)接口的RDNSS功能開啟情況:
netsh int ipv6 sh int Idx number
執(zhí)行以下命令關(guān)閉RDNSS功能(將Idx number替換為要關(guān)閉的網(wǎng)絡(luò)接口的Idx值):
netsh int ipv6 set int Idx number rabaseddnsconfig=disable
樣例輸出如下:
此時再次確認(rèn)接口的RDNSS開啟情況,RDNSS功能已被關(guān)閉:
二、漏洞復(fù)現(xiàn)
1. 環(huán)境搭建
l 靶機:Windows 10 1809 x64
l 靶機操作:無需任何操作,可正常與攻擊機通信即可
2. 復(fù)現(xiàn)過程
1. 通過各種手段獲取目標(biāo)主機的IPv6地址和MAC地址(具體方法可自行探索,較為簡單)
2. 攻擊機python3運行poc:
3. 靶機crash:
三、漏洞分析
1. 基本信息
- 漏洞文件:tcpip.sys
- 漏洞函數(shù):Ipv6pUpdateRDNSS()函數(shù)
- 漏洞對象:ICMPv6路由廣播中的option結(jié)構(gòu)
2. 背景知識
限于篇幅問題,此處不對用于DNS配置的IPv6路由廣播進行詳細(xì)介紹,更詳細(xì)資料可參考RFC8106。
1. 基本知識
IPv6 Router Advertisment (RA) options,也稱為DNS RA options,允許IPv6的路由器向IPv6的主機廣播DNS Recursive Server Address(DNS遞歸路由器地址)列表和DNS Search List(DNS搜索列表),其主要用途為在IPv6的主機上進行DNS名稱解析以及域后綴的處理。
IPv6 Neighbor Discovery(ND,IPv6鄰居發(fā)現(xiàn))和IPv6 Stateless Address Autoconfiguratioin(SLAAC,IPv6無狀態(tài)地址自動配置)提供了使用一個或多個IPv6地址,默認(rèn)路由器以及一些其他參數(shù)配置固定節(jié)點或移動節(jié)點的方法。
當(dāng)漫游主機每次連接到另一個網(wǎng)絡(luò)時,無法進行手動配置。 雖然可以進行靜態(tài)配置,但是在諸如筆記本電腦之類的通用主機上通常不建議這樣操作。 例如,如果主機運行直接連接到全局DNS的自己的遞歸名稱服務(wù)器,那么本地定義的名稱空間對主機來說就不可用了。 訪問DNS是幾乎所有主機的基本要求,因此IPv6 SLAAC在沒有任何DNS配置支持的情況下,不能在任何實際的網(wǎng)絡(luò)環(huán)境中單獨作為替代部署模型。
對于IPv4環(huán)境中的DNS服務(wù)器來說,這些問題都很容易解決。但是對于IPv6的網(wǎng)絡(luò)環(huán)境,這些問題顯得比較棘手。因此,RFC8106定義了一種基于DNS RA選項的機制,以允許IPv6主機執(zhí)行自動DNS配置。
在通過IPv6 SLAAC自動配置IPv6主機地址并且沒有DHCPv6基礎(chǔ)結(jié)構(gòu)或一些主機沒有DHCPv6客戶端的網(wǎng)絡(luò)環(huán)境中,可以使用基于RA的DNS配置作為替代。 但是,對于需要分發(fā)其他信息的網(wǎng)絡(luò),可能仍然會使用DHCPv6。 在這些網(wǎng)絡(luò)中,可能不需要基于RA的DNS配置。 基于RA的DNS配置允許IPv6主機獲取主機連接到的鏈接的DNS配置(即DNS遞歸服務(wù)器地址和DNSSL)。 此外,主機會從提供鏈接配置信息的同一RA消息中學(xué)習(xí)此DNS配置。
2. 名詞解釋
- Recursive DNS Server (RDNSS):遞歸DNS服務(wù)器,提供遞歸DNS解析服務(wù)的服務(wù)器,用于將域名轉(zhuǎn)換為IP地址或解析成RFC1034和RFC1035中定義的PTR記錄。
- RDNSS Option:一個用于向IPv6主機傳送RDNSS信息的IPv6的RA option【RFC4861】。
- DNS Search List (DNSSL):Pv6主機在執(zhí)行DNS查詢搜索時使用的DNS后綴域名列表,用于搜索簡短的不合格域名。
- DNSSL Option:一個IPv6 RA選項,用于將DNSSL信息傳遞到IPv6主機。
3. 詳細(xì)分析
1. 基礎(chǔ)分析
RFC8106標(biāo)準(zhǔn)化了RDNSS option,其中包含RDNSSes的地址。該信息使用現(xiàn)有ND message(例如RA)作為載體。IPv6主機可以通過RA消息配置一個或多個RDNSS的IPv6地址。
(1) 鄰居發(fā)現(xiàn)擴展
RFC8106中定義的在鄰居發(fā)現(xiàn)中使用的IPv6 DNS配置算法需要用到2種ND options:RDNSS option和DNSSL option。與該漏洞相關(guān)的是RDNSS option,另外一種則與 CVE-2020-16899相關(guān)。
(2)RDNSS Option Structure
RDNSS option總體結(jié)構(gòu)如下:
對于Length字段,如果該選項中僅包含一個IPv6地址,則最小值為3。 每增加一個RDNSS地址,長度就會增加2。接收的主機使用該字段來確定選項中IPv6地址的數(shù)量。
(3)Procedure in IPv6 Hosts
當(dāng)主機接收到RA消息中的DNS的options時,其處理過程如下:
- 首先檢查Lengh字段的合法性:是否大于等于最小值3,以及是否滿足(Length - 1) % 2 == 0;
- 對于RDNSS option,還會檢查Address字段是否為一個單播地址;
- 如果以上驗證通過,則主機應(yīng)按順序?qū)⑦x項的值復(fù)制到DNS存儲庫和解析器存儲庫中。 否則,主機必須丟棄這些選項。
(4)Crash分析
首先分析dmp文件,查看crash現(xiàn)場:
并沒有發(fā)現(xiàn)明顯的較為有價值的Call Stack信息,但是發(fā)現(xiàn)最終的crash原因的是GS機制的Security Cookie校驗失敗,也就是說該值被覆蓋掉了。那么很有可能是一個溢出。除此之外,只發(fā)現(xiàn)了tcpip!Ipv6pHandleRouterAdvertisement+0x1269函數(shù),再往后就直接報gsfailure了。
2. 靜態(tài)分析
分析使用的文件為Windows 10 1809 x64的tcpip.sys文件,版本為10.0.17763.316。
(1)函數(shù)調(diào)用鏈
根據(jù)crash現(xiàn)場信息,獲取到關(guān)鍵函數(shù)tcpip!Ipv6pHandleRouterAdvertisement(),首先確認(rèn)該函數(shù)到漏洞函數(shù)的前后調(diào)用鏈。
首先查看其交叉引用關(guān)系:
其上層調(diào)用函數(shù)為Icmpv6ReceiveDatagrams(),跟進,并查看交叉引用關(guān)系:
沒有再發(fā)現(xiàn)顯式的函數(shù)調(diào)用。轉(zhuǎn)而向tcpip!Ipv6pHandleRouterAdvertisement()的下層搜索:
發(fā)現(xiàn)漏洞函數(shù)調(diào)用。至此,函數(shù)調(diào)用鏈可以簡單概括為:
- Icmpv6ReceiveDatagrams() -> tcpip!Ipv6pHandleRouterAdvertisement() -> Ipv6pUpdateRDNSS()
(2)漏洞函數(shù)分析
經(jīng)過簡單分析可以明確,調(diào)用鏈的頂層函數(shù)Icmpv6ReceiveDatagrams()沒有發(fā)現(xiàn)實質(zhì)性的與該漏洞相關(guān)的處理代碼,而在tcpip!Ipv6pHandleRouterAdvertisement() 函數(shù)中發(fā)現(xiàn)了對漏洞函數(shù)Ipv6pUpdateRDNSS()的調(diào)用。根據(jù)crash分析,最后報了gsfailure,而且關(guān)鍵函數(shù)為tcpip!Ipv6pHandleRouterAdvertisement(),在該函數(shù)的起始位置確實發(fā)現(xiàn)了GS校驗:
那么很有可能是在漏洞函數(shù)Ipv6pUpdateRDNSS()中發(fā)生了溢出,導(dǎo)致了其調(diào)用函數(shù)tcpip!Ipv6pHandleRouterAdvertisement()的GS校驗失敗。
進入漏洞函數(shù)Ipv6pUpdateRDNSS():
首先獲取到RDNSS option結(jié)構(gòu),然后讀取Length字段來計算Address字段有幾個Address值。
確認(rèn)有多少Address之后,進入循環(huán),對每個Address進行處理,最關(guān)鍵的是分配合適的內(nèi)存。這里還有一個判斷,如果不是單播地址,直接忽略。
在進行處理時,存在一個問題:假設(shè)Length的長度為4,那么計算結(jié)束之后,AddressCount的值應(yīng)該為1。此時,按照正常邏輯,Ipv6pUpdateRDNSS()函數(shù)應(yīng)該增加32字節(jié)(4*8)的緩沖區(qū),但是后續(xù)在分配緩沖區(qū)時只分配了24字節(jié):sizeof(ND_OPTION_RDNSS) + sizeof(IN6_ADDR) = 8 + 16 = 24,從而導(dǎo)致了緩沖區(qū)的溢出。
根據(jù)RFC8106的標(biāo)準(zhǔn),Length字段的值應(yīng)該滿足最小為3的奇數(shù)的情況。當(dāng)提供一個偶數(shù)Length值時,Windows TCP/IP堆棧錯誤地將buffer前進了8個字節(jié)。這主要是因為堆棧在內(nèi)部以16字節(jié)為增量進行計數(shù),并且沒有使用非RFC兼容長度值的處理代碼。這種不匹配導(dǎo)致堆棧將當(dāng)前選項的最后8個字節(jié)解釋為第二個選項的開始,最終導(dǎo)致緩沖區(qū)溢出和潛在的RCE。
4. 利用思路
1. 利用條件
基本條件
- attacker需要獲取target的IPv6和MAC地址
觸發(fā)過程
- attacker需要搭配其他內(nèi)存泄漏或信息泄漏漏洞來實現(xiàn)RCE
- attacker需要想辦法繞過tcpip.sys的GS保護機制
2. 利用過程
attacker直接發(fā)送特制的ICMPv6路由廣播數(shù)據(jù)包給target:
[ Attacker ]
3. 攻擊向量
建立連接后,利用IPv6直接發(fā)送攻擊數(shù)據(jù)包即可。
5. 流量分析
因為該漏洞直接走的IPv6,所以對于一些部署在IP層以上的防火墻方案就無法針對該漏洞進行流量檢測,但是具備IP層流量檢測的防火墻可以輕松檢測惡意流量:
在流量中可以明顯看出,第一個Option結(jié)構(gòu)的Address字段錯誤識別計算了一個Recursive DNS Server的值:
第1個Recursive DNS Server的地址為0018-0027,后續(xù)的8個字節(jié)不應(yīng)該再進行識別。選中第2個Recursive DNS Server時情況如下:
第2個Recursive DNS Server的地址為0028-0037。但是該16個字節(jié)中的后8個字節(jié)很明顯為下一個ICMPv6 Option結(jié)構(gòu)的內(nèi)容:
四、參考文獻
- https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-16898
- https://tools.ietf.org/html/rfc8106
- https://www.mcafee.com/blogs/other-blogs/mcafee-labs/cve-2020-16898-bad-neighbor/