作者:Numen Cyber Labs
原文鏈接:https://mp.weixin.qq.com/s/5oBAw-oLtHA52-0eBcPSpg

背景和準備

微軟上月發布的補丁包含一個可能執行代碼的TCP/IP協議漏洞。為了驗證該漏洞的影響范圍和可能后果,Numen 高級安全研究團隊對此漏洞做了深入的分析,并通過補丁對比,還原出了PoC。本文將詳細介紹我們如何通過補丁對比還原出PoC,以及漏洞的細節。Numen 將會持續輸出高質量的安全研究文章,以及成果,為Web3安全以及網絡安全其他領域提供權威高質量的研究成果,助力網絡安全健康發展。

首先熟悉這些與IPv6和IPSec ESP協議相關的數據包結構有助于理解本文。技術參考如下:

IPv6:https://www.rfc-editor.org/rfc/rfc2460#page-6

IPSec ESP: https://www.rfc-editor.org/rfc/rfc2406

補丁分析

有了之前的知識,我們可以更容易地理解脆弱性原理。現在讓我們分析補丁。

比較tcpip.sys的八月和九月補丁,我們發現有兩個函數需要修補。如下所示:

這里的補丁修補方式表明在重組ipv6分片數據的時候,似乎存在某一個內存偏移大于預期的可能錯誤。除此之外,還有另一個修補過的函數:

這處函數修補作用并不太直觀,我們只能知道接收IPsec_ESP封包的處理過程中,如果其某一標志位不滿足補丁修補條件,這個包將會被丟棄。

PoC 構造

A. 初步嘗試

盡管Microsoft在漏洞描述中明確表示,它將向啟用IPSec的節點發送ipv6數據包。然而,從上面對漏洞補丁的分析來看,我們認為如果我們能夠構建一個符合Ipv6pReassembleDatagram函數中修補條件的IPv6碎片數據,我們可以觸發內存中錯誤(大于預期)偏移量的損壞。

一開始,我們忽略了IPSec的條件,專注于IPV6碎片化和包重組。tcpip DOS漏洞分析CVE-2021-24086 2021年初(https://blog.quarkslab.com/analysis-of-a-windows-ipv6-fragmentation-vulnerability-cve-2021-24086.html)提供了一個良好的切入點

參考本文中的PoC,我們可以在Ipv6pReassembleDatagram函數中重新組織一組IPV6分區包。但我們發現,只有普通ipv6標頭攜帶碎片數據包,這不會影響補丁中限制的參數。

查看漏洞的官方描述,并注意第二個補丁。我們認為可能有必要使用IPSec中的ESP包來控制第一個補丁的關鍵參數。

我們開始構建啟用IPSec協議的測試環境。

B. 構造IPSec流量包

如前介紹,IPSec是一種可以對指定類型ip流量篩選過濾,并加密驗證的一種協議。通常在VPN或者增強其他協議密碼安全性的部分條件下使用。在windows中

我們搭建了一個域條件下,兩臺對對方所有流量都加密驗證的環境。因為很多時候它并不是一種默認開啟的協議。

為了構造這種數據包,我們必須知道協議中指定的加密算法和秘鑰。其中IPSec_ESP中加密方式我們可以自行選擇。在本次分析中我們僅僅啟用了IPSec中的完整性HASH驗證,使用SHA1計算hash。但這已經能滿足漏洞觸發的基本要求。

這里需要額外說明IPSec數據包構造過程中數據加密的秘鑰獲取(如果選擇linux作為攻擊機的話,密鑰獲取將比較容易可以忽略這里)。

Windows中的IPSec的加密過程都是在tcpip協議驅動中實現的,雖然在應用層中,微軟提供了一套WFP流量篩選平臺框架API可以控制IPSec中SA的一些參數(如SPI),但是對于秘鑰管理這一部分,我們并不能直接獲取到IPSec_ESP包中加密所需的秘鑰和其他的一些具體的加密規則(不同于流量加密秘鑰每次的變化,流量完整性驗證秘鑰雖然也會不停變化,但在一段時間內,該秘鑰是固定的)。

通過分析tcpip驅動,我們可以從tcpip的MICROSOFT_TCPIP_PROVIDER_Context中獲取密鑰(在測試環境,我們直接從內核中BCryptCreateHash的參數中獲取)。并且如前所述,我們的IPSec流量中,只啟用了流量完整性驗證,并沒有使用流量加密。這樣對后續的分析,協議理解都比較直觀。

構造好IPSec流量包后,通過調整IPSec數據包中的參數,我們的數據包滿足了第二個修補函數對IPSec_ESP包在第二處補丁函數對指定標志的限制條件。對照協議結構,我們可以知道,第二處補丁函數限制的標志位對應的是IPSec_ESP包中加密數據的類型標志。當ESP中加密包ipv6擴展頭類型為小于等于0時丟棄該數據包。具體包括一下幾項0(IPv6 Hop-by-Hop Option)或者0x2b(Routing Header for IPv6)0x2c(Fragment Header for IPv6)

我們的測試中,使用了Fragment Header for IPv6的包(0x2c)。

C. 最終的 PoC

有了我們需要的IPSec流量包結構后,我們現在需要做的就是將第一步嘗試構造的IPv6分片數據當做ESP協議中需要被加密以及驗證的數據(其中關鍵是ESP尾部結構中最后一位標志ESP攜帶的擴展頭類型標志設為0x2c),并組裝好后開始發送。

由于該漏洞需要發送原始ip數據包,并且在初期調試的過程中,最好能夠比較方便的控制修改每一個發送的ip包字節。我們需要一個比較底層且靈活的發包接口。喜歡python的朋友可以使用scapy。

我們這里使用的是一個現成的NDIS協議驅動。(該驅動代碼和編譯及安裝。參考《windows網絡通訊程序設計第二版》代碼示例)。使用底層驅動協議的好處是除了個人習慣,另外有很多的各類型協議數據包組裝代碼示例方便理解。

總結

從根本上講,該漏洞修復主要限制ESP攜帶IPv6 IPSec協議中提到的幾個IPv6擴展頭。

當前PoC代碼可能導致NetIo協議頭對象內容中的字節(大于0x38的任意偏移地址)被重寫為任意值(此處為0x2C)。這里提到的0x2c不是ESP中攜帶的第一個ipv6擴展標頭類型標志。它是ESP中攜帶的分區標頭旁邊的ipv6擴展標頭標志。這可以任意設置。

在解析下一個擴展頭時,我們可以通過構造一些準確的擴展頭來崩潰esp包。如果隨后的esp解密內容無效且與擴展頭類型不一致,TCPIP通常不會立即觸發異常(通過控制內存損壞的位置,我們可以構建一些不同類型的系統崩潰場景):

對于該漏洞的利用,目前有兩種思路。

A、 重點分析目前我們可能損壞的NetIo協議頭對象的詳細結構,看看數據大小或其他關鍵數據位置是否可以通過我們寫入的數據轉換為其他緩沖區復制錯誤,從而構建任意讀/寫函數。

B、 因為我們可以破壞的位置不限于NetIo協議頭對象,我們可以通過構造更大的偏移量(通過修改ESP包的長度)來覆蓋其他對象。因此,可以使用其他對象來構造讀/寫源語言或代碼執行。

但無論上述哪一種想法,都可能需要進一步分析其確切的可行性

實際影響

從漏洞本身的范圍來看,該漏洞依賴于IPv6協議和IPSec協議的組合。IPv6目前被廣泛使用。有許多場景支持IPv6,但一些常用的VPN或一些需要流量加密的環境通常不使用IPSec作為默認選項,需要由管理員設置。

此外,我們的PoC在域中設置了兩個IP安全策略的環境中實現。首先,我們通過域驗證身份,然后我們可以向其他受信任的域成員目標發送易受攻擊的數據包。未經身份驗證發送的加密流量將不會被處理。否則,您需要獲得預共享的密鑰才能完成身份驗證。

漏洞PoC詳情, 請訪問:https://github.com/numencyber/VulnerabilityPoC


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1996/