winrar(CVE-2023-38831)漏洞原理
2024-3-6 17:53:52 Author: mp.weixin.qq.com(查看原文) 阅读量:6 收藏


背景

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文件系统不允许同一路径下存在同名的文件或文件夹,但是可以通过一些途径绕过此限制。
1.创建一个test.txt1文件和一个test.txt2文件夹,在test.txt2文件夹中创建一个test.txt3.cmd,写入打开计算机,然后打包成zip文件。
2.使用16进制编辑器,如010Editor,对压缩文件中的文件名进行更改。
这里代表有3个文件,我们把txt后面的数字123都改成空格,空格x`对应的acsll码是0x20。

再去看压缩包发现文件夹和文件已经是同名的。

此时去双击test.txt 文件,会发现.cmd文件被执行了,弹出了计算机,且临时目录下提取了两个文件。
至此,Winrar代码执行漏洞复现完毕,下面我们了解下,这个过程发生了什么,为什么要该掉一个字符为空格(0x20)?为什么点击了一个文件却解压出来了两个文件?为什么test.txt .cmd被执行了?
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在处理一个文件时会通过文件路径获取文件的扩展名(PathFindExtension),然后通过注册表和**AssocQueryString**等文件关联函数获取绑定了扩展名的关联程序(例:.xml文件的关联程序:MS Edge微软浏览器)的绝对路径,最后将创建进程所需的ModuleFileName参数设置为获取到的绝对路径,CommandLine参数设置为文件的绝对路径,并调用CreateProcessW启动进程。
如果没找到扩展名,则会对当前目录下的所有同名文件进行遍历,如果存在同名文件且是可执行文件(com、cmd、bat、exe等)则使用该可执行文件作为进程的模块地址。若找不到同名文件,或没有找到扩展名的关联程序,那么会弹出窗口让用户自己选择要使用的处理程序。
该文件为正常的.txt文本文件,后面无空格。此时再到CreateProcessW断点处,可以看到ModuleFIleName(lpApplicationName)参数被设置为notepad++的地址,CommandLine参数被设置为test.txt文件地址,这些参数都是Shellexecute进行设置的。
Shellexecute会通过.txt后缀名在注册表中找到绑定的ProgID(一般在默认键值中),如果没设置默认值也可以在子键OpenWithProgID中找到绑定的ProgID,随后根据ProgID找到注册的处理程序的路径地址,将之设为ModuleFilName参数的值。
注意,test.txt后面有个空格,此时就变成了最初看到的情况,test.txt .cmd被设置成了创建进程的参数。
接下来我们通过逆向ShellExecute函数看看为什么加了空格后,原本的执行逻辑就改变了。
ShellExecute在Shell32.dll中,大致执行流程如下图所示,我们只关注的核心的标红函数,这三个函数是最终的问题所在,但他们不在Shell32.dll而是在Shlwapi.dll中。
路径字符串末尾为空格或”\“就会返回指向NULL的指针(windwos文件系统在创建文件时首部和尾部会自动把空格清除)。
该函数没找到符号文件,IDA解析时有问题,故用了另一位博主B1tg的图。通过伪代码可以看出如果路径长度超过最大长度或在最后一个点后再次出现空格或\都会返回指向NULL的字符串指针,即未找到后缀名。这也是为什么把最后一个字符串改成空格的原因。
当未找到后缀名时会进入sub_63192842函数中。
这个函数的主要功能是遍历当前路径下的所有文件,并将文件后缀和一个数组比较,数组中是windwos系统下常见可执行文件的后缀名。
对遍历到的文件进行比对,返回数组下标。
所以test.txt 文件因为.后面出现的空格返回了Null,导致if中的表达式为False,于是进入了sub_63192842函数中,搜索到了test.txt .cmd文件,最终该文件被返回并设置了进程创建的参数完成了代码执行。
当然如果同一路径下也没发现这6种可执行路径的后缀则会启动rundll32程序,加载shell32的OpenAs_RunDLL函数弹出对话框,让用户选择要执行的程序。


总结

触发该漏洞的完整调用链大致如上所述,究其原因还是Winrar程序本身在双击文件预览时错误的释放逻辑,以及WindowsApi Shellexecute在根据后缀名寻找相应执行文件时触发本地搜索的特性,二者结合才形成了完整的漏洞利用链条。

看雪ID:time.time

https://bbs.kanxue.com/user-home-967913.htm

*本文为看雪论坛优秀文章,由 time.time 原创,转载请注明来自看雪社区

# 往期推荐

1、ELF文件脱壳纪事

2、Glibc-2.35下对tls_dtor_list的利用详解

3、对旅行APP的检测以及参数计算分析【Simplesign篇】

4、2023强网杯warmup题解

5、Directory Opus 13.2 逆向分析

6、Pwn-oneday题目解析

球分享

球点赞

球在看

点击阅读原文查看更多


文章来源: https://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458544969&idx=1&sn=473822d99738dc8c20cf0c7df866adea&chksm=b18d5bc386fad2d597b3b73e9bbd6d243e83e0191527db7cf84f277ac8c455b590956d5da778&scene=58&subscene=0#rd
如有侵权请联系:admin#unsafe.sh