文章总结: 本文详细解析了Vue路由守卫的绕过原理,指出客户端守卫仅用于UI控制而非安全防御。文章通过代码审计演示了两种绕过方式:一是直接篡改Pinia/Vuex内存中的认证状态;二是在本地存储中伪造Token。核心结论是前端防护不可靠,必须在服务端进行严格的权限验证。 综合评分: 88 文章分类: WEB安全,代码审计,安全开发,漏洞分析
从源码解析 Vue 路由守卫绕过原理
船山信安
2026年1月15日 17:00 湖南
基础知识:什么是 Vue 路由守卫?
在 Vue.js 单页应用(SPA)中,页面跳转并不会刷新浏览器,而是由 vue-router 动态替换组件。为了控制用户访问权限(例如:未登录用户不能访问后台),开发者通常会使用 全局前置守卫
简单来说,路由守卫就像是小区门口的保安:
-
to: 你要去哪里?(目标路由) -
from: 你从哪里来?(来源路由) -
next: 是否放行?(控制跳转)
一个典型的守卫代码如下:
router.beforeEach((to, from, next) => {
// 如果目标路由需要权限,且用户未认证
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login'); // 拦截,踢回登录页
} else {
next(); // 放行
}
});
绕过方式一:客户端状态直接篡改
-
场景: 应用依赖前端内存中的状态(如 Pinia/Vuex)来判断用户是否登录
-
目标: 不登录直接访问 Admin 页面
代码审计
我们拿到了靶场的源码,重点关注两个文件:src/router.js(路由配置)和 src/stores/auth.js(状态管理)
审计 src/router.js
// 创建 Vue Router 实例
const router = createRouter({
// 使用 HTML5 History 模式(需要服务器配置支持)
history: createWebHistory(),
// 定义路由表
routes: [
// 首页路由,路径 '/' 对应 Home 组件
{ path: '/', component: Home },
// 登录页路由,路径 '/login' 对应 Login 组件
{ path: '/login', component: Login },
// 管理员页面路由
{
path: '/admin',
component: Admin,
// [1] meta 字段用于存储路由元信息
// requiresAuth: true 标记此路由需要用户认证才能访问
meta: { requiresAuth: true }
}
]
})
// 注册全局前置守卫,在每次路由跳转前执行
router.beforeEach((to, from, next) => {
// [2] 获取认证状态存储(假设使用 Pinia)
// 注意:在 Vue 3 中,需确保在 setup 上下文中调用 useAuthStore()
const authStore = useAuthStore()
// [3] 核心判断逻辑:检查目标路由是否需要认证且用户未登录
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
// 输出警告信息到控制台
console.warn('⛔ Access Denied: User not authenticated.')
// 跳转到登录页面,中断当前导航
next('/login')
} else {
// 放行路由跳转(包括不需要认证的路由和已认证用户)
next()
}
})
审计 src/stores/auth.js
export const useAuthStore = defineStore('auth', () => {
// 【漏洞警示:纯客户端状态】
// 此 isAuthenticated 状态仅在客户端内存中维护,
// 攻击者可通过浏览器开发者工具轻松修改其值为 true,
// 从而绕过前端路由守卫的认证检查
const isAuthenticated = ref(false) // [4] 默认未认证状态
// ...
// 暴露状态和方法供组件使用
return { isAuthenticated, login, logout }
})
审计分析
isAuthenticated 只是一个普通的 Vue ref,存储在浏览器的内存中。整个认证逻辑完全运行在客户端
既然判断依据只是浏览器内存中的一个变量,作为客户端的控制者,我们可以随意修改这个变量的值
绕过方式二:本地存储伪造
为了实现“保持登录状态”,开发者通常会将 Token 存储在 localStorage 或 sessionStorage 中
很多开发者写出了类似这样的路由守卫代码:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
const token = localStorage.getItem('token');
// 仅仅检查 Token 是否存在 (Existence Check)
if (token) {
next(); // 放行
} else {
next('/login'); // 拦截
}
} else {
next();
}
});
打开浏览器控制台输入
localStorage.setItem('token', 'i_am_a_hacker_token');
来源:https://xz.aliyun.com/ 感谢【用户wEXYxrAEhI】
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:船山信安 《从源码解析 Vue 路由守卫绕过原理》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论