背景介绍
WinRAR是最受欢迎的压缩工具之一,在全球拥有超过5亿用户。2023年7月10日,国外威胁情报机构Group-IB研究DarkMe恶意软件传播时,在WinRAR处理ZIP文件格式中发现了一个未知的漏洞。通过利用该程序中的漏洞,威胁行为者能够制作ZIP存档,作为各种恶意软件系列的载体。2023年8月15日,MITRE Corporation将此零日漏洞标记为CVE-2023-38831。
漏洞详情
漏洞受影响范围:5亿WinRAR用户;
漏洞受影响版本:WinRaR<v6.23所有版本;
漏洞复现
WinRAR在小于6.23版本中点击压缩包中的文件预览时,错误的将被点击的文件名和同名文件夹下的所有文件释放到临时目录中,随后调用Shellexecute执行文件造成代码执行。
正常情况下windows文件系统不允许同一路径下存在同名的文件或文件夹,但是可以通过一些途径绕过此限制。
01 创建一个test.txt1文件和一个test.txt2文件夹,在test.txt2文件夹中创建一个test.txt3.cmd,写入打开计算机,然后打包成zip文件;
02 使用16进制编辑器,如010Editor,对压缩文件中的文件名进行更改;
这里代表有3个文件,我们把txt后面的数字123都改成空格,空格x对应的acsll码是0x20;
再去看压缩包发现文件夹和文件已经是同名的;
此时去双击test.txt 文件,会发现.cmd文件被执行了,弹出了计算机,且临时目录下提取了两个文件。
至此,WinRAR代码执行漏洞复现完毕,下面我们了解下这个过程发生了什么。
-
为什么要改掉一个字符为空格(0x20)?
-
为什么点击了一个文件却解压出来了两个文件?
-
为什么test.txt .cmd被执行了?
WinRAR的执行流程
WinRAR是一个GUI程序,在用户双击一个文件预览时会发送一个WM_LBUTTONDOWN消息,然后主程序根据此消息获得点击的文件名,也就是click_name,随即主程序会遍历压缩包中所有的deFileName(文件夹也在此列),当deFileName==click_name那么该文件就会被释放出来并写入临时目录中,也就是说同名文件夹下的所有文件都会被释放出来。最终WinRAR会初始化ShellExecuteInfo结构体,将click_name释放后的路径设置到lpFileName中,并调用Windows系统APi ShellExecute函数执行该文件。
我们通过调试逆向的方式看到整个流程确实是这样的,而且在调用Shellexecute函数时可以看到文件名也确实是test.txt 。为什么最终是test.txt.cmd被执行了。带着这个问题继续往下看,我们知道一个程序被运行是要加载到进程空间的,因此Shellexecute函数最终也会调用CreateProcess等函数来创建进程,于是在进程创建函数上下断点进行调试运行。
此时断点命中CreateProcessW,但这里发现一个问题,WinRAR在调用ShellexecuteW时lpFileName参数明明是"test.txt ",后面调用CreateProcesssW创建进程时却变成了”test.txt .cmd“。很明显ShellexecuteW做了一些我们不知道的操作,更改了参数。那ShellExecute做了什么就变成了了解问题的关键。
ShellExecute函数
ShellExecute在处理一个文件时会通过文件路径获取文件的扩展名(PathFindExtension),然后通过注册表和AssocQueryString等文件关联函数获取绑定了扩展名的关联程序(例:xml文件的关联程序:MS Edge微软浏览器)的绝对路径,最后将创建进程所需的ModuleFileName参数设置为获取到的绝对路径,CommandLine参数设置为文件的绝对路径,并调用CreateProcessW启动进程。
以正常的test.txt文件为例
该文件为正常的.txt文本文件,后面无空格。此时再到CreateProcessW断点处,可以看到ModuleFIleName(lpApplicationName)参数被设置为notepad++的地址,CommandLine参数被设置为test.txt文件地址,这些参数都是ShellExecute进行设置的。
ShellExecute会通过.txt后缀名在注册表中找到绑定的ProgID(一般在默认键值中),如果没设置默认值也可以在子键OpenWithProgID中找到绑定的ProgID,随后根据ProgID找到注册的处理程序的路径地址,将之设为ModuleFilName参数的值。
左右滑动查看更多
以恶意的test.txt 文件为例
注意,test.txt后面有个空格,此时就变成了最初看到的情况,test.txt .cmd被设置成了创建进程的参数。
接下来我们通过逆向ShellExecute函数看看为什么加了空格后,原本的执行逻辑就改变了。
ShellExecute函数逆向
ShellExecute在Shell32.dll中,大致执行流程如下图所示,我们只关注的核心的标红函数,这三个函数是最终的问题所在,但他们不在Shell32.dll而是在Shlwapi.dll中。
PahtFileExistsDefExtAndAttributesW
路径字符串末尾为空格或”“就会返回指向NULL的指针(windwos文件系统在创建文件时首部和尾部会自动把空格清除)。
PathFindExtensionw
该函数没找到符号文件,IDA解析时有问题,故用了另一位博主B1tg的图。通过伪代码可以看出如果路径长度超过最大长度或在最后一个点后再次出现空格或都会返回指向NULL的字符串指针,即未找到后缀名。这也是为什么把最后一个字符串改成空格的原因。
当未找到后缀名时会进入sub_63192842函数。
sub_63192842
这个函数的主要功能是遍历当前路径下的所有文件,并将文件后缀和一个数组比较,数组中是windwos系统下常见可执行文件的后缀名。
对遍历到的文件进行比对,返回数组下标。
所以test.txt 文件因为.后面出现的空格返回了Null,导致if中表达式的结果为False,于是进入了sub_63192842函数中,搜索到了test.txt .cmd文件,最终该文件被返回并设置了进程创建的参数完成了代码执行。
当然如果同一路径下也没发现这6种可执行路径的后缀则会启动rundll32程序,加载shell32的OpenAs_RunDLL函数弹出对话框,让用户选择要执行的程序。
总结
触发该漏洞的完整调用链大致如上所述,究其原因还是Winrar程序本身在双击文件预览时错误的释放逻辑,以及WindowsApi Shellexecute在根据后缀名寻找相应执行文件时触发本地搜索的特性,二者结合才形成了完整的漏洞利用链条。
我们时刻关注客户需求,为您搭建更高效的新一代智能安全运营协同作战体系。如果您想了解更详细的支持信息,可联系下方邮箱进行咨询!
原文始发于微信公众号(众智维安):典型漏洞分析 | WinRAR
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论