Files
reverse-skill/skills/field-journal/2026-05-16_pentest-personalblog-fun-mass-assignment.md
T
2026-08-08 18:32:33 +08:00

5.1 KiB
Raw Blame History


name: pentest-personalblog-fun-mass-assignment description: {target_domain} Spring Boot 博客系统渗透测试——通过 Swagger 泄露 + Mass Assignment 提权至管理员,JS静态分析补充攻击面 metadata: type: project

{target_domain} 渗透测试记录

日期: 2026-05-16 目标: https://www.{target_domain}/ 关键词: Spring Boot, MyBatis-Plus, SaToken, Mass Assignment, Swagger泄露, 权限提升, Vue 3, JS静态分析, 前端路由绕过, DTO缺失

背景

黑盒渗透测试一个基于 Spring Boot 的个人博客系统,目标是进入后台管理页面。

攻击路径

  1. 信息收集: 识别 Vue SPA → 提取 JS 中的 API 端点 → 发现 /api/v3/api-docs(Swagger 未授权访问)
  2. API 文档分析: 获得完整端点定义、数据模型、管理员接口
  3. 用户枚举: 文章列表接口暴露 admin 用户信息(id=1,email={admin_email})
  4. 公告提示漏洞存在: 公告 #14 标注"网站普通用户可被提权管理员"
  5. 注册: 通过 mail.tm 临时邮箱接收验证码注册普通用户
  6. Mass Assignment 提权: PUT /api/user/profile 传入 "role":"admin" 将 role 从 reader 提升为 admin

JS 静态分析补充发现

IP 被限速后通过前端 JS bundle 做静态分析,提取了完整的 API 端点列表:

来源 发现
user-n8GFLR5I.js 全部 16 个用户/认证端点的完整参数定义
article-manage-BUHBK4I3.js 全部 8 个文章端点的操作(CRUD + 发布/草稿/列表)
upload-C3Isuhzt.js 文件上传逻辑(avatar + cover),使用 FormData/multipart
Login-BfQvQsk0.js 登录/注册完整流程,含邮箱验证码登录
index-F3rwNCiG.js axios 实例配置(baseURL: /api, satoken header)

前端路由保护发现

Vue Router 定义中管理端路由带 requiresAdmin: true 标志,但仅在前端判断:

{ path: "/user-manage", name: "UserManage", ..., meta: { requiresAdmin: true } },
{ path: "/category-manage", name: "CategoryManage", ..., meta: { requiresAdmin: true } },

后端 API 虽然有 SaToken 鉴权,但管理端 GET 接口(如 article/all)缺少认证检查。

完整 API 端点清单

用户/Auth(user-n8GFLR5I.js):

  • POST /user/login — 用户名密码登录
  • POST /user/register — 注册
  • GET /user/info — 当前用户信息
  • PUT /user/profile — 更新资料(Mass Assignment!)
  • PUT /user/password — 修改密码
  • POST /user/logout — 登出
  • POST /auth/send-code — 发验证码
  • POST /auth/verify-email-code — 校验验证码
  • POST /user/login-by-email — 邮箱验证码登录
  • GET /user/check-username / check-email / check-exists — 检查接口
  • PUT /user/{id}/status — 管理员禁用用户
  • GET /user/{id} — 管理员查用户详情
  • GET /user/list — 管理员用户列表

文章(article-manage-BUHBK4I3.js):

  • POST /article — 创建文章
  • PUT /article/{id} — 更新文章
  • DELETE /article/{id} — 删除文章
  • GET /article/{id} — 查文章详情
  • GET /article/drafts — 我的草稿
  • GET /article/my — 我的文章
  • GET /article/all — 所有文章(管理端)
  • POST /article/{id}/publish — 发布文章

已验证安全的攻击面

测试项 结论
密码修改需旧密码 PUT /user/password 需要旧密码认证
邮箱验证码一次性 验证码消费后不可重用
前端无 API Key/Secret 硬编码 bundle 中无敏感凭证
SaToken UUIDv4 不可伪造 UUID 随机性足够
nginx 正确拦截 Method Override HTTP 动词篡改被 405 拒绝

关键发现

发现 说明
Swagger 生产环境未关闭 /api/v3/api-docs + Knife4j + Swagger UI 全暴露
MyBatis-Plus 直接接受 Entity Controller 直接接收 User 对象传给 updateById,未做字段过滤
CORS 全通 access-control-allow-origin: *
邮箱验证码可用 temp mail mail.tm 临时邮箱可接收验证码
前端路由保护仅前端控制 requiresAdmin 标志在后端无对应强制校验
系统级 Mass Assignment Article/Category/Tag/Announcement 全部 CRUD Entity 直收
article/all 无认证 管理端文章列表接口未做任何权限校验

复现命令

# 注册
POST /api/user/register {"username":"x","password":"{test_password}","email":"{test_email}","emailCode":"123456"}
# 提权
PUT /api/user/profile {"role":"admin"}
# 验证
GET /api/user/info → {"role":"admin",...}
GET /api/user/list → [全部用户]

工具

  • curl (Windows)
  • mail.tm API (临时邮箱)
  • Python 3
  • JS 源码静态分析(regex/py 提取端点)

修复要点

  1. DTO 隔离:Controller 不要直接接收 Entity 对象(全局审计)
  2. @JsonIgnore 或 Service 层 role 字段强制写保护
  3. 生产禁用 Swagger/Knife4j
  4. CORS 限制为具体域名
  5. 用户信息接口脱敏
  6. Article/all 添加 SaCheckRole 注解
  7. 后端对所有管理端接口做独立权限校验(不依赖前端路由控制)

关联