Vite任意文件读取漏洞分析(CVE-2025-30208)
Vite, a provider of frontend development tooling, has a vulnerability in versions prior to 6.2.3, 6.1.2, 6.0.12, 5.4.15, and 4.5.10.
@fs
denies access to files outside of Vite serving allow list. Adding?raw??
or?import&raw??
to the URL bypasses this limitation and returns the file content if it exists. This bypass exists because trailing separators such as?
are removed in several places, but are not accounted for in query string regexes. The contents of arbitrary files can be returned to the browser. Only apps explicitly exposing the Vite dev server to the network (using--host
orserver.host
config option) are affected. Versions 6.2.3, 6.1.2, 6.0.12, 5.4.15, and 4.5.10 fix the issue.
从漏洞描述可以看到影响版本如下:
6.2.0 <= version <=6.2.2
6.1.0 <= version <=6.1.1
6.0.0 <= version <=6.0.11
5.0.0 <= version <=5.4.14
version <=4.5.9
漏洞环境
漏洞环境已上传github:Vul-Env/Vite/CVE-2025-30208 at main · Cmisl/Vul-Env
Vite版本:v6.2.0
node版本 :v20.9.0
操作系统:Windows11
运行以下指令启动环境:
1 |
|
漏洞复现
根据漏洞POC,并且当前环境系统是Windows。如果是Linux系统就把C://windows/win.ini换成etc/passwd即可。
1 |
|
漏洞分析
在Vite中,@fs
是一个用于处理文件系统访问的机制,主要用于开发模式下访问项目根目录外的文件。当通过import
或require
引入根目录外的文件时,Vite会将路径转换为以/@fs/
开头的绝对路径形式,例如/@fs/app/vite/packages/vite/dist/client/env.mjs
由于一些原因我并没有搭建调试环境进行代码调试,因此分析只是粗糙地分析一下了,大概看了一下绕过鉴权的地方如下:
其中rawRE和urlRE如下:
1 |
|
将url与上面两个正则表达式进行匹配,匹配情况如下。
输入 | 是否匹配 | 匹配部分 |
---|---|---|
?raw |
是 | ?raw |
&raw |
是 | &raw |
?raw&foo |
是 | ?raw& (部分) |
?rawn |
否 | - |
?raw#anchor |
否 | - |
?raw? |
否 | - |
关于url的也同理,我们在回头看这条if判断语句: |
1 |
|
在计算机中,对于&&运算符,如果前面的语句为false,那么&&后的语句是不会执行的。举个例子,下面代码我们运行之后不会输出任何东西,并且由于printHelloWorld方法不被调用,因此里面的语句也不会输出。
而&&前面的语句为true,那么后面的语句才会去执行,也因此调用了printHelloWorld方法,输出了里面的语句。
因此对于POC中的URL:http://localhost:5173/@fs/C://windows/win.ini?import&raw??
,由于两个正则表达式都不会去匹配,因此&&前语句为false,后面的鉴权函数不会被调用。
然后就是对import的处理了。
removeImportQuery这里的处理逻辑是把匹配到的替换成第一个捕获组,也就是(\?|&)
匹配到的字符,这里就是?import&
替换成?
,接着又会匹配结尾的?
或者&
。
漏洞修复
看一下这个diff,添加了一个正则表达式常量 trailingQuerySeparatorsRE
,用于匹配 URL 末尾的一个或多个查询分隔符(?
或 &
)。
然后在 transformMiddleware
函数中处理 URL,将 URL 中末尾的查询分隔符去掉,并将结果存储
在 urlWithoutTrailingQuerySeparators
变量中。将原本直接使用 url
的地方,改为使用处理后的 urlWithoutTrailingQuerySeparators
。
来避免rawRE和urlRE的匹配为false从未不会调用鉴权的方法。
漏洞修复
已经发布了新版本,都在原来的基础上打了补丁,直接升级到新版本即可,安全版本如下:
6.2. 3 <=version
6.1. 2 <= version <6.2.0
6.0.12 <= version <6.1.0
5.4.15 <= version <6.0.0
4.5.10 <= version <5.0.0