天天看點

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

作者:蟲蟲安全

最近Fortigate裝置暴露出一個非常嚴重(9.8分)的遠端執行漏洞。裝置商Fortinet已于上個月8日悄悄釋出了更新,修補了漏洞,随即安全公告中披露了該漏洞,稱該漏洞可能已被用于有針對性的攻擊。

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

近日,安全人員釋出的一項研究顯示,在網際網路公網上仍然暴露了愈336,000台裝置仍然容易受到該漏洞的影響,這些裝置還未安裝官方更新檔。本文蟲蟲就來分析一下該漏洞的的詳細分析、利用和緩解方法,供大家學習參考。

概述

CVE-2023-27997是FortigateVPN遠端代碼執行,該VPN包含在其硬體防火牆中。 該漏洞源于堆溢出錯誤,嚴重程度為9.8分(滿分10分)。研究人員表示,盡管更新檔的嚴重性和可用性,但管理者修複它的速度很慢。

上周五Bishop Fox援引Shodan搜尋引擎查詢中檢索到的資料表示,在網際網路上暴露的489,337台裝置中,有335,923台(即69%)還未修補更新檔。甚至,有些裝置,自從2015以來就沒有從未更新過固件。Bishop Fox的漏洞驗證腳本顯示:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

螢幕截圖顯示了漏洞的概念驗證,程式利用堆溢出損壞并注入惡意代碼,連接配接到攻擊者控制的伺服器,下載下傳類Unix作業系統的BusyBox實用程式,并打開一個互動式shell,該shell允許易受攻擊的計算機遠端發出指令。該漏洞僅需要大約一秒鐘即可完成。

漏洞細節

漏洞位于允許使用者對VPN進行身份驗證的Web界面。界面在設計上是面向網際網路的,其接口為/remote/hostcheck_validate,,通過GET或 POST,可以發送一個名為enc參數

enc參數是一個包含種子、大小(2 位元組)和資料的結構。大小和資料均已加密。

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

種子存儲為8個十六進制字元,用于計算XOR密鑰流的第一個狀态:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

sa是伺服器建立的随機值,可以通過向接口/remote/info發出GET請求來檢索該值。

密鑰流的其他狀态計算如下:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞
Fortigate防火牆裝置存身遠端代碼執行高危漏洞

密鑰流S可以與其餘部分進行異或enc有效負載、大小和密文,以解密它們。它以十六進制字元串發送。

解密方法如下(簡化代碼):

Fortigate防火牆裝置存身遠端代碼執行高危漏洞
Fortigate防火牆裝置存身遠端代碼執行高危漏洞

函數parse_enc_data的行為如下:

計算MD5(16 位元組),這是來自鹽和種子的密鑰的第一個狀态(前 8 個字元) in)

配置設定大小的緩沖區in_len/2 + 1, out,以及十六進制解碼輸入到其中

計算使用者給出的長度, given_len,通過将有效負載的前兩個位元組與密鑰的前兩個位元組進行異或。

邊界檢查:驗證給定的長度不大于緩沖區的大小。

就地解密整個字元串:異或前 14 個位元組,然後計算新狀态 K 1 ,用它對接下來的 16 個位元組進行異或,然後重複。

在解密資料的末尾放置一個NULL位元組。

将解密的值添加到包含HTTP輸入參數的哈希圖中。

漏洞位于當程式檢查給定長度不大于發送的有效負載的長度時,它會比較 in_len和given_len。但是,雖然前者以十六進制描述有效負載的長度(例如 '41424343'),後者以原始位元組描述其大小(例如 'ABCD')。 是以,given_len可以是應有的兩倍。

這個錯誤使的不僅可以将解密過程應用于out,而且也為了之後的記憶。這導緻了一個有趣的錯誤:不隻可以覆寫堆中的位元組,而是使用一些MD5對它們進行異或!

理論驗證

該錯誤允許配置設定任意大小的塊N,然後将緩沖區後的位元組與MD5哈希值的密鑰流進行XOR為此部分控制密鑰。控制配置設定的緩沖區的大小以及異或溢出的大小。 此外,溢出的最後一個位元組被清空。

一個想法

首先可以想到的是對某個位址的LSB進行異或以改變其位置,類似如此:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

然而,該計算比較昂貴的:需要找到一個以306300000000。開頭的MD5哈希值。 該散列是另一個散列的散列,這是另一個散列的散列,等等。例如,如果散列到要修改的指針的距離是0x1000,則這将是密鑰流的第256個狀态。一次計算并不困難,但暴力破解......

即使設法拿到了這樣的散列,該修改後的指針之前的資料也會出現亂碼,因為它會與之前的散列進行異或,無法選擇其内容。

jemalloc配置設定器

由于聽起來很難讓任何東西正常工作,是以浏覽底層配置設定器,看看是否有任何方法可以利用該錯誤。

底層堆jemalloc:

堆中繼資料獨立存儲; 可以安全地從一個塊(區域)溢出到另一個塊(區域)

可以輕松獲得連續的配置設定(填補漏洞後)

對于相同大小的配置設定有某種LIFO機制:釋放一塊大小N并配置設定相同的大小會産生相同的指針。

最後一點實際上使利用變得更加容易:可以配置設定溢出的緩沖區,out,在同一位址,重複。

強大的原語

一旦觸發該錯誤,它就會看起來像是一個糟糕的原語。然而,由于可以一緻地配置設定out在記憶體中的同一位置進行多次緩沖,原語變得非常好。事實上,知道對一個值應用兩次相同的XOR會使其保持不變:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

如果使用完全相同的參數(種子和長度)觸發錯誤兩次,并且如果兩次ou緩沖區被配置設定在相同的記憶體位址,溢出中的每個位元組都會與相同的值進行異或兩次。 除了一個位元組被設定為NULL之外,記憶體完全沒有改變。一項改進:一種将位元組設定為零的方法,沒有副作用。

此外,使用相同的種子觸發錯誤兩次,隻有第一次将溢出長度設定為L,第二次到L+1,産生更好的結果。

在第一次疊代中,會完全搞亂資料,直到偏移處的位元組L,将為NULL。在第二次疊代中,每個位元組都會與密鑰進行異或兩次,進而再次變成原來的自己,除了Bl,這将取值KL ,作為0⊕ KL= KL 。改變L+1将變為NULL。

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

是以,給位元組L任意值X,可以計算一個密鑰流,這樣KL = X ,并應用原語兩次,一次使用長度L,一次長度L + 1。

這是一個例子:我們要設定B[5000] 到0X50。計算一個種子,使得K[5000] = 0X50。這是8 th位元組250th 狀态,是以S250 [8] = 0X50。 例如,如果鹽是e0b638ac ,可以使用種子00690000擷取:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

然後應用長度為4999的原語。我們得到以下結果:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

第二次應用它,長度為5000

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

記憶體不變,除了位元組5000,現在有值0X50和5001,現在為NULL。

這是一個很好的原語:現在有一種方法可以編輯記憶體中的位元組。

更高效率的方法

我們實際上可以做得更好,連續覆寫幾個位元組,每個位元組一個請求。比如想給記憶體寫入e ABC\0,溢出緩沖區後的e ABC\0位元組。首先計算一個種子s0

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

然後,計算一個種子s1這樣:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

接着S2種子的:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

然後将第一個位元組設定為零(長度:L):

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

然後以相反的順序應用帶有種子的原語,s2到s0 ,長度L + 1 至L + 3 。得到,對于s2:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

s1:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

以及s0:

Fortigate防火牆裝置存身遠端代碼執行高危漏洞

通過使用4原語次,可以成功将ABC寫到了記憶體中。但是,該技術有一個巨大的缺陷,因為它弄亂了修改記憶體之前的所有内容。

結論

該漏洞Fortinet已于6月8日修複。修複版本為7.2.5、 7.0.12、6.4.13和 6.2.15 ,請低于這些版本的裝置抓緊更新。

繼續閱讀