深入Vite任意文件读取与分析复现
字数 1169 2025-08-29 22:41:32

Vite任意文件读取漏洞分析与复现指南

漏洞概述

本漏洞是Vite开发服务器中存在的一个任意文件读取漏洞,攻击者可以通过精心构造的URL请求读取服务器上的任意文件,包括敏感系统文件如C:/Windows/win.ini等。

环境搭建

  1. 创建Vite项目:

    npm create vite@latest
    
  2. 安装依赖:

    cd your-project
    npm install
    
  3. 运行开发服务器:

    npm run dev
    

漏洞复现

有效Payload

Windows系统:

http://localhost:3000/@fs/C:/Windows/win.ini?raw
http://localhost:3000/@fs/C:/Windows/win.ini?raw??

Linux系统:

http://localhost:3000/@fs/etc/passwd

测试说明

  • 对于Windows系统,需要包含raw参数
  • 多个问号??可以绕过某些检查
  • Linux系统不需要特殊参数,直接请求文件路径即可

漏洞分析

Vite执行流程

  1. 入口点cli.js是Vite的入口文件,具体入口函数是createServer
  2. 服务器创建createServer调用_createServer函数
  3. 中间件注册_createServer会注册一系列中间件,顺序很重要:
    • servePublicMiddleware
    • transformMiddleware
    • 其他中间件...

关键中间件分析

1. servePublicMiddleware

  • 无论是否有cleanUrl,最终执行next()时URL保持不变
  • 对漏洞利用影响不大,只是传递请求到下一个中间件

2. transformMiddleware

关键处理逻辑:

  1. 移除时间戳查询参数

    url = removeTimestampQuery(url)
    
    • 移除形如t=1234567890123的时间戳参数
    • 处理后的URL会减少问号数量
  2. 公共路径检查

    if (url.startsWith(publicPath + '/') || url === publicPath) {
      warnAboutExplicitPublicPathInUrl(url, publicPath, timestamp)
    }
    
    • 检查URL是否以public开头
    • 仅打印警告,不影响请求处理
  3. 请求类型判断

    if (!(rawRE.test(url) || urlRE.test(url))) {
      return next()
    }
    
    • 需要满足raw参数或特定URL模式才会继续处理
    • 多个问号可以绕过此检查
  4. 文件类型判断

    if (isJSRequest(url) || isImportRequest(url))
    
    • isJSRequest: 检查是否为JS请求或没有后缀的请求
    • isImportRequest: 检查是否包含import参数

核心漏洞点

  1. 文件加载阶段

    pluginContainer.load(id, { ssr })
    
    • id参数最终被处理为文件路径(如C:/Windows/win.ini
    • 经过cleanUrl处理后,查询参数被移除
  2. 路径处理缺陷

    • Vite没有正确限制@fs前缀的访问范围
    • 对Windows路径和Linux路径的处理存在逻辑缺陷

漏洞利用条件

  1. Windows系统

    • 必须包含raw参数
    • 可以附加额外的问号绕过检查
  2. Linux系统

    • 不需要特殊参数
    • 直接请求文件路径即可

防御建议

  1. 升级到已修复的Vite版本
  2. 在开发环境中限制文件系统访问范围
  3. 避免在生产环境使用Vite开发服务器
  4. 实施严格的路径验证和过滤

总结

该漏洞源于Vite开发服务器对@fs前缀的处理不当,结合查询参数的解析缺陷,导致攻击者可以读取任意文件。理解该漏洞有助于开发者更好地保护自己的应用,同时也展示了中间件处理顺序和安全检查的重要性。

Vite任意文件读取漏洞分析与复现指南 漏洞概述 本漏洞是Vite开发服务器中存在的一个任意文件读取漏洞,攻击者可以通过精心构造的URL请求读取服务器上的任意文件,包括敏感系统文件如 C:/Windows/win.ini 等。 环境搭建 创建Vite项目: 安装依赖: 运行开发服务器: 漏洞复现 有效Payload Windows系统: Linux系统: 测试说明 对于Windows系统,需要包含 raw 参数 多个问号 ?? 可以绕过某些检查 Linux系统不需要特殊参数,直接请求文件路径即可 漏洞分析 Vite执行流程 入口点 : cli.js 是Vite的入口文件,具体入口函数是 createServer 服务器创建 : createServer 调用 _createServer 函数 中间件注册 : _createServer 会注册一系列中间件,顺序很重要: servePublicMiddleware transformMiddleware 其他中间件... 关键中间件分析 1. servePublicMiddleware 无论是否有 cleanUrl ,最终执行 next() 时URL保持不变 对漏洞利用影响不大,只是传递请求到下一个中间件 2. transformMiddleware 关键处理逻辑: 移除时间戳查询参数 : 移除形如 t=1234567890123 的时间戳参数 处理后的URL会减少问号数量 公共路径检查 : 检查URL是否以 public 开头 仅打印警告,不影响请求处理 请求类型判断 : 需要满足 raw 参数或特定URL模式才会继续处理 多个问号可以绕过此检查 文件类型判断 : isJSRequest : 检查是否为JS请求或没有后缀的请求 isImportRequest : 检查是否包含 import 参数 核心漏洞点 文件加载阶段 : id 参数最终被处理为文件路径(如 C:/Windows/win.ini ) 经过 cleanUrl 处理后,查询参数被移除 路径处理缺陷 : Vite没有正确限制 @fs 前缀的访问范围 对Windows路径和Linux路径的处理存在逻辑缺陷 漏洞利用条件 Windows系统 : 必须包含 raw 参数 可以附加额外的问号绕过检查 Linux系统 : 不需要特殊参数 直接请求文件路径即可 防御建议 升级到已修复的Vite版本 在开发环境中限制文件系统访问范围 避免在生产环境使用Vite开发服务器 实施严格的路径验证和过滤 总结 该漏洞源于Vite开发服务器对 @fs 前缀的处理不当,结合查询参数的解析缺陷,导致攻击者可以读取任意文件。理解该漏洞有助于开发者更好地保护自己的应用,同时也展示了中间件处理顺序和安全检查的重要性。