原文鏈接:“Game of Rars” – Exploring a New Remote Code Execution Vulnerability in WinRAR with Proof-of-Concept (CVE-2023-40477)
譯者:知道創宇404實驗室翻譯組
摘要
- 擁有5億以上用戶的WinRAR,曝出新的漏洞(CVE-2023-40477,CVE-2023-38831);
- CVE-2023-40477的PoC
- 雖然被認為是RCE假定可被利用,但實際上影響并不大;
- 本文研究內容包括:其影響、可被利用的場景以及緩解措施;
- 該漏洞已在最新的Winrar v6.23中得到修復,本文也會提出解決辦法。
CVE-2023-40477:概述和PoC
八月中旬,WinRAR 6.23發布了一些關于關鍵漏洞的警告。我們了解到漏洞(CVE-2023-40477)目前已經修復,且公布了以下信息,具體內容詳看下文:

二進制文件對比
我們知道6.23版本已經修復,為了復現找到了修復前的版本。通過下載便攜版的WinRAR-v6.23和WinRAR-v6.22,觀察了解到:

可以看到winrar.exe可能只是一個圖形界面,如果在解壓過程中存在漏洞,那么它也可能存在于“unrar.exe”中。通過對比6.23和6.22的差異(忽略注釋),我們得到以下結果:

查看流程圖,6.23版本中發現了幾個有趣的新增內容(大型函數圖中,看起來像是主要的提取):

仔細觀察,這些似乎是額外的檢查!

這看起來很有希望!我們在這里看到一些var < 255!!有趣的是,這里看起來進行了溢出檢查。所以是時候觸發漏洞了(例如將字節更改為最大值)。
我對RAR格式進行了研究,從描述中我們知道這與RAR4(vol3?)恢復卷有關,因此我生成了具有這些特性的RAR4文件,它給出了以下文件列表:
- RAR_FILE.rar
- RAR_FILE.r00
- RAR_FILE00.rev
- RAR_FILE.r01
- RAR_FILE01.rev
我嘗試對".rev"和"rXX"卷中“類字節”的值進行了暴力破解,但沒有成功。它沒有觸發任何內容。 接著嘗試搜索一些"unrar"源代碼 ,然后成功找到了這個舊的存儲庫:https://github.com/aawc/unrar
查看源代碼,可以看到多個"255"常量檢查,尤其是在"recvol3.cpp"中。它們也出現在最初的6.22源代碼中,難道是因為溢出而添加了額外的檢查?
在深入研究的過程中,我發現實際上這些安全檢查均與0xff / 255有關。
漏洞

在這里,P[i]’s是從 ".rev" 文件中提取的。它們位于文件末尾。這些P[i]’s用于確定它們代表哪個恢復卷以及適用于哪個 FileNumber。FileNumber 也從中獲取,存儲在 P[2] 中。
緊接著,在我們控制的索引位置上分配并放置了 File\ ,而這個數組的大小是256!(第241行),而這解釋了為什么有255次檢查。
因為該索引實際上等于:P[2]+P[0]-1,我們幾乎可以任意控制rev卷的內容。因此,我們可以用指針(指向 File 結構)來覆蓋該緩沖區,它們將覆蓋當前對象中的下一個屬性。
Poc撰寫
為了觸發該漏洞,我們發現需要在recvol3.cpp中調用"Restore()"函數。此外還需要進行重建步驟,以便對指針進行覆寫。
為了實現這一點,需要有一些缺失的rar卷(.r00文件缺失),以及可用的.rev文件。此外,還要確保crc32校驗正確,而這只需要幾行代碼就能進行觸發。
為了方便起見,使用了通過GUI生成的原始rar4恢復卷,但是這可以使用更小且更高效的觸發方式,且最多可能只需2-3個文件。
# 1. re-generate malformed recovery vols.
data = open('%s01.rev' % ARCHIVE_NAME, 'rb').read() # just use the first and malform it up.
names = ['%s%s.rev' % (ARCHIVE_NAME, str(i).zfill(2)) for i in range(256)]
# "destroy" the P[i]'s
datas = [data[:-7] + bytes([0xf0, 0x00, i]) + calc_crc(data[:-7] + bytes([0xf0, 0x00, i])) for i in range(256)]
# 2. overwrite malformed recovery vols.
for i in range(256):
fname = names[i]
data = datas[i]
open(fname, 'wb').write(data)
在發現漏洞后不久,還看到了rar-labs網站上的https://www.rarlab.com/vuln_rev3_names.html, 這基本上證實了我們的發現。
利用這一點,成功地在幾種情況下使winrar/unrar崩潰:
- 內存集用零覆蓋無效內存(可能在緩沖區之后):


- 在使用“提取到”功能時,winrar.exe中可能出現堆溢出的情況

利用性
為了確定可利用性,看看在256個數組之后覆蓋的結構。以此來確定攻擊者如何利用這個原語來獲取遠程代碼執行(RCE),以及存在哪些緩解措施。
// RecVolume3 struct - that gets overflowed
class RecVolumes3
{
private:
File *SrcFile[256]; // overflow in here with File* pointers.
Array Buf;
#ifdef RAR_SMP
ThreadPool *RSThreadPool;
#endif
public:
RecVolumes3(CommandData *Cmd,bool TestOnly);
~RecVolumes3();
void Make(CommandData *Cmd,wchar *ArcName);
bool Restore(CommandData *Cmd,const wchar *Name,bool Silent);
void Test(CommandData *Cmd,const wchar *Name);
};
...
...
// Array template class:
template class Array
{
private:
T *Buffer;
size_t BufSize;
size_t AllocSize;
size_t MaxSize;
public:
Array();
Array(size_t Size);
Array(const Array &Src); // Copy constructor.
~Array();
總而言之,我們用“File*”指針溢出“Buffer”對象,同還需要繞過這里啟用的許多防御措施。 幸運的是,里面有很多保護措施:ASLR、CFG、Stack-Cookie和DEP。
這還沒有提到winrar版本之間的二進制差異。盡管可能存在漏洞利用的潛力,但對于普通黑客來實際上的利用可能性并不高。
影響
盡管其CVE等級很高,但成功利用漏洞所需的復雜性表明廣泛濫用的可能性很低,這與廣泛利用的Log4j RCE漏洞不同。
有趣的是,Chromium似乎也使用了unrar庫:https://chromium.googlesource.com/chromium/src/+/6ff23b0604e2edbe7ef282564ea340f5c72ab91a%5E%21/.
盡管沒有代碼參考表明其使用情況,但unrar庫有可能作為第三方依賴項被集成到Chrome OS中。
解決措施
可考慮的應對措施:
-
完全修復:將Winrar更新到6.23+將完全修復。
-
補丁修復:如果更新不可用或難以部署,可以考慮阻止使用*.rev文件(最好同時阻止*.rXX文件和*.partXX.rar文件)。盡管并沒有官方支持肯定,但這可能是目前的一個快速的修復方法。
參考鏈接
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/3019/
暫無評論