--- 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` 标志,但**仅在前端判断**: ```javascript { 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 无认证** | 管理端文章列表接口未做任何权限校验 | ## 复现命令 ```bash # 注册 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. 后端对所有管理端接口做独立权限校验(不依赖前端路由控制) ## 关联 - [[swagger-exposure-pentest]]