“Game of Rars” – 通过概念验证探索 WinRAR 中新的远程代码执行漏洞 (CVE-2023-40477) –
2023-9-2 12:45:28
Author: Ots安全(查看原文)
阅读量:21
收藏
执行摘要
- WinRAR 拥有超过 500 亿用户,面临新漏洞(CVE-2023-40477、CVE-2023-38831)。
- 今天,我们首次展示:CVE-2023-40477 的 PoC(撰写本文时)
- 尽管 RCE 被认为是可利用的,但由于多种原因,它在现实中的影响看起来并不乐观。
- 我们在此介绍全面的技术研究:其影响、可利用的场景和缓解措施。
- 该漏洞已在最近的 Winrar v6.23 中修复,我们在这里还提供了另一种缓解措施
CVE-2023-40477:技术概述和概念验证
现在是 8 月中旬,Winrar 6.23 发布了,并带有一些关于严重漏洞的模糊警报。我们所知道的是 – 漏洞 (CVE-2023-40477) 已修复,并且以下信息:配备 BinDiff、IDA 和记事本,让我们深入研究。比较二进制文件
我们知道 6.23 已修复,让我们尝试查找修复前后的最小版本,以便我们可以观察它。我已经下载了便携式 winrar-v6.23 + winrar-v6.22 并观察了它:
人们可以立即观察到 winrar.exe 可能只是一个 GUI,如果提取中存在漏洞 - 它也可能存在于“unrar.exe”中。比较 6.23 和 6.22 给了我以下差异(忽略评论;)):通过查看流程图,我在 6.23 中添加了一些有趣的内容(在大函数图中——看起来像是主要的提取):
这看起来很有希望!我们在这里看到一些 var < 255 的额外检查!有趣的。看起来这里有溢出检查权限。
因此,是时候触发了(即将字节更改为最大值)。我查看了 RAR 格式,从描述中我们知道这与 RAR4(vol3?)恢复卷有关,
因此我生成了具有这些功能的 RAR4,它给了我一个文件列表,如下所示:
我尝试暴力破解“.rev”和“rXX”卷中任何“类字节”值的内容,但没有成功。它没有触发或改变任何东西。
然后,我尝试谷歌搜索一些“unrar”源代码——也许它作为其他项目的一部分存在?!
成功!我找到了这个旧存储库:https://github.com/aawc/unrar现在查看源代码,我们看到多个“255”常量检查,特别是在“recvol3.cpp”中,它们也出现在原始 6.22 源代码,所以也许他们添加了额外的源代码,因为……溢出?
让我们检查一下,更深入地研究,我发现安全检查实际上与 0xff / 255 相关。
漏洞
recvol3.cpp 内的 CVE-2023-40477这里,P[i]是从“.rev”文件本身中提取的。它们位于文件末尾。
这些P[i]用于确定它们代表哪个恢复卷以及它们适合什么FileNumber 。
FileNumber也在P[2]中从它们检索。
紧接着,File*被分配并放置在我们控制的大小为 256 的数组中的索引中!(第 241 行)。
这就解释了 255 次检查。
因为索引实际上等于:P[2]+P[0]-1。我们几乎可以通过“rev”卷内容任意控制它。
所以,毕竟,我们可以用指针覆盖该缓冲区(指向文件结构),它们会覆盖当前对象中的下一个属性。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)
我们的 PoC @ https://github.com/wildptr-io/Winrar-CVE-2023-40477-POC/
找到它后不久,我们还在 rar-labs 网站上看到了https://www.rarlab.com/vuln_rev3_names.html,这很有可能证实了我们的发现。使用它,我们在几种情况下成功地崩溃了 winrar / unrar:
1.Memset 用零覆盖无效内存(可能在缓冲区之后):使用 winrar 的 unrar.exe 时崩溃 – 在Buf的 memset 上2.使用“提取到”时 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 版本之间的二进制差异。所有这些都使得利用成为可能,但对于普通威胁行为者来说可能性不大。
文章来源: http://mp.weixin.qq.com/s?__biz=MzAxMjYyMzkwOA==&mid=2247501220&idx=3&sn=964292d264a5e7fe5dd29ac68513bcb1&chksm=9bad8cefacda05f9ceb10664e432aeffe1de7a0934d847aacc7fb0c3c432d08ce9191d1e62fa&scene=0&xtrack=1#rd
如有侵权请联系:admin#unsafe.sh