---
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]]
