java-file-upload-audit
SKILL.md
Java 文件上传漏洞审计工具
分析 Java Web 项目源码,识别文件上传实现并检测上传相关漏洞风险(任意文件上传、路径穿越、文件覆盖、Web 根目录可执行等)。
核心要求
此技能必须完整分析所有上传相关代码,不允许省略。
- ✅ 识别所有上传入口点(ServletFileUpload / MultipartFile / transferTo / FileItem)
- ✅ 标注每个上传点的保存路径、文件名来源与校验策略
- ✅ 检测所有潜在的上传风险模式(类型校验缺失、路径穿越、Web 根目录写入、文件覆盖)
- ✅ 当源码不可用时必须反编译,并输出反编译文件清单(文件名 + 位置)
- ❌ 禁止省略任何上传入口
- ❌ 禁止跳过反编译步骤
漏洞分级标准
- 漏洞编号格式:
{C/H/M/L}-UPLOAD-{序号} - 严重等级 = f(可达性 R, 影响范围 I, 利用复杂度 C)
- Score = R × 0.40 + I × 0.35 + C × 0.25,映射 CVSS 3.1
| 前缀 | CVSS 3.1 | 含义 |
|---|---|---|
| 🔴 C | 9.0-10.0 | 可直接导致系统沦陷 |
| 🟠 H | 7.0-8.9 | 可造成重大损害 |
| 🟡 M | 4.0-6.9 | 可造成一定损害 |
| 🔵 L | 0.1-3.9 | 安全加固建议 |
技能协作流程(CRITICAL)
java-file-upload-audit 应在 java-route-mapper 之后执行,基于已梳理的路由信息进行审计。
┌─────────────────────────────────────────────────────────────────┐
│ 完整审计流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [步骤1] java-route-mapper │
│ │ │
│ │ 输出: │
│ │ ├─ 所有 HTTP 路由列表 │
│ │ ├─ 每个路由的参数定义 │
│ │ │ ├─ 参数名、类型 │
│ │ │ └─ JSON 内部字段 │
│ │ └─ Burp Suite 请求模板 │
│ │ │
│ ↓ │
│ [步骤2] java-file-upload-audit(本技能) │
│ │ │
│ │ 输入:java-route-mapper 的输出 │
│ │ │
│ │ 执行: │
│ │ ├─ 快速扫描上传实现 │
│ │ ├─ 参数-上传映射分析 │
│ │ ├─ 校验逻辑与保存路径分析 │
│ │ └─ 执行条件分析 │
│ │ │
│ ├─── 需要深入追踪 ───→ java-route-tracer │
│ │ │ │
│ │ ←── 返回调用链信息 ────┘ │
│ │ │
│ ↓ │
│ [步骤3] 输出综合审计报告 │
│ │
└─────────────────────────────────────────────────────────────────┘
输入依赖(来自 java-route-mapper)
在开始审计前,应先检查是否已有 java-route-mapper 的输出文件:
{project_name}_audit/
├── route_mapper/
│ └── {route_name}/
│ └── {project_name}_routes_{timestamp}.md ← 检查此文件
└── file_upload_audit/
└── {route_name}/
└── {project_name}_file_upload_audit_{timestamp}.md ← 本技能输出
如果 route_mapper 输出不存在,建议先运行:
Skill(skill="java-route-mapper", args="--project {project_path}")
从 route_mapper 获取的关键信息
| 信息 | 用途 |
|---|---|
| 路由路径 | 定位上传 Controller/Servlet 入口 |
| 参数名 + 类型 | 识别 MultipartFile / FileItem / fileName 参数 |
| JSON 内部字段 | 识别嵌套上传参数 |
| 参数用途描述 | 判断是否用于文件名或保存路径 |
工作流程(三阶段)
阶段1: 快速扫描(优先执行)
目标:快速定位上传相关代码,不遗漏关键点。
# 1.1 Servlet/Commons FileUpload
rg -n "ServletFileUpload|DiskFileItemFactory|FileItem|isMultipartContent" --glob="*.java"
# 1.2 Spring Boot MultipartFile
rg -n "MultipartFile|@RequestParam\\(\"file\"\\)|transferTo\\(" --glob="*.java"
# 1.3 文件名/路径相关
rg -n "getOriginalFilename|getName\\(\\)|getRealPath\\(\"/uploads\"\\)|uploadDir" --glob="*.java"
rg -n "new File\\(|Paths\\.get\\(|Path\\.of\\(|File\\.separator" --glob="*.java"
# 1.4 上传接口路由
rg -n "@PostMapping\\(|@RequestMapping\\(.*upload|/upload" --glob="*.java"
输出:高危文件清单(按优先级排序)
| 优先级 | 文件类型 | 审计重点 |
|---|---|---|
| P0 | *Controller.java / *Servlet.java 中包含 upload 逻辑 |
MultipartFile/FileItem |
| P1 | *Service.java, *ServiceImpl.java |
文件保存路径/重命名 |
| P2 | *Util.java, *Storage.java, *File*.java |
通用存储封装 |
| P3 | *Config.java, application.yml |
文件大小/目录配置 |
阶段2: 参数-上传映射分析
基于 route_mapper 输出,分析每个上传参数是否影响文件名或保存路径。
2.1 高危参数识别
| 参数来源 | 参数名 | 类型 | 风险 |
|---|---|---|---|
| @RequestParam | file |
MultipartFile | 高危 - 直接上传 |
| FileItem | item |
FileItem | 高危 - fileName 可控 |
| @RequestParam | fileName |
String | 高危 - 文件名拼接 |
| JSON | upload.path |
String | 高危 - 目录拼接 |
2.2 参数追踪(示例)
HTTP 参数: file (MultipartFile)
↓
Controller.handleFileUpload(file)
↓
file.getOriginalFilename() ← 文件名来源
↓
Paths.get(uploadDir).resolve(fileName)
↓
file.transferTo(filePath) ← 上传写入点
2.3 上传点检查
对每个上传写入点,检查:
-
文件名来源是否可控?
getOriginalFilename()/item.getName()→ 高危- 服务器生成随机名 → 低危
-
是否有路径规范化与目录限制?
getCanonicalPath()+ 固定上传目录 → 较安全- 直接拼接路径 → 高危
-
是否做类型/内容校验?
- 白名单扩展名/Content-Type/魔数校验 → 安全
- 仅检查非空或无校验 → 高危
-
上传目录是否在 Web 根目录?
getRealPath("/uploads")//uploads/→ 高风险- 非 Web 可访问目录 → 较安全
阶段3: 深入分析与报告
当上传逻辑复杂或参数多层传递时,调用 java-route-tracer 获取完整调用链并补充校验路径分析。
上传实现识别(来自 Notion 资料的关键点)
1) Servlet/Commons FileUpload
识别特征:
ServletFileUpload.isMultipartContent(request)DiskFileItemFactory/ServletFileUploadupload.parseRequest(request)→List<FileItem>item.getName()作为文件名item.write(storeFile)写入文件getServletContext().getRealPath("/uploads")作为保存目录
Notion 记录要点:
- 示例未校验表单字段名,
name="file"不会被校验。 - 仅设置了大小上限(如
upload.setSizeMax(5MB)),未见扩展名/类型/路径校验。
2) Spring Boot MultipartFile
识别特征:
@RequestParam("file") MultipartFile filefile.getOriginalFilename()file.transferTo(filePath)- 固定上传目录
uploadDir = "/uploads/"
Notion 记录要点:
@RequestParam("file")会校验表单字段名,需要name="file"。- 示例未见文件名净化、类型白名单或目录隔离。
详细检测规则参见 UPLOAD_RULES.md
反编译阶段(CRITICAL)
当源码不可用时,必须使用 MCP Java Decompiler 反编译上传相关类。
反编译工具调用
# 反编译单个上传相关类
mcp__java-decompile-mcp__decompile_file(
file_path="/path/to/UploadController.class",
output_dir="/path/to/decompiled",
save_to_file=True
)
# 反编译上传相关目录
mcp__java-decompile-mcp__decompile_directory(
directory_path="/path/to/WEB-INF/classes/com/example/upload",
output_dir="/path/to/decompiled",
recursive=True,
save_to_file=True,
max_workers=4
)
# 反编译多个指定文件
mcp__java-decompile-mcp__decompile_files(
file_paths=[
"/path/to/UploadController.class",
"/path/to/FileStorageService.class",
"/path/to/UploadUtil.class"
],
output_dir="/path/to/decompiled",
save_to_file=True
)
必须反编译的类
| 类型 | 匹配模式 | 目的 |
|---|---|---|
| Controller/Servlet | *Upload*Controller.class, *Servlet.class |
提取上传入口 |
| Service/Storage | *Storage*.class, *FileService*.class |
追踪保存路径 |
| 工具类 | *UploadUtil*.class, *FileUtil*.class |
查找通用校验 |
| 配置类 | *Config*.class |
获取上传目录/大小限制 |
反编译输出要求:
- 输出“反编译文件清单”,包含原始文件名与反编译输出路径
- 反编译文件路径需可定位到具体目录
执行条件分析(CRITICAL - 避免误报)
发现上传逻辑后,必须分析该逻辑是否真的会被执行!
| 检查项 | 说明 | 影响 |
|---|---|---|
| 权限校验 | 仅管理员可访问 | 影响可利用性 |
| 参数校验 | 字段名/类型/大小校验 | 降低风险 |
| 目录限制 | 固定上传目录 | 降低路径穿越 |
| 可访问性 | 上传目录是否可 Web 访问 | 决定是否可执行 |
结论分级必须标注:✅ 已确认可利用 / ⚠️ 待验证 / ❌ 不可利用 / 🔍 环境依赖
报告生成
输出单个综合审计报告文件:
{project_name}_audit/file_upload_audit/
└── {route_name}/
└── {project_name}_file_upload_audit_{timestamp}.md
路由名说明:
- 路由名从路由路径提取,去掉前缀斜杠和特殊字符
- 例如:
/api/file/upload→api_file_upload
输出格式
综合报告模板
# {项目名称} - 文件上传漏洞审计报告
生成时间: {timestamp}
分析路径: {project_path}
---
## 1. 审计概述
| 项目 | 信息 |
|------|------|
| 审计范围 | {project_path} |
| 上传实现 | {ServletFileUpload / MultipartFile / 其他} |
| 分析方法 | 静态代码审计 + 数据流分析 |
---
## 2. 风险统计
| 严重等级 | CVSS | 数量 | 说明 |
|----------|------|------|------|
| 🔴 C (Critical) | 9.0-10.0 | {count} | 可直接导致系统沦陷 |
| 🟠 H (High) | 7.0-8.9 | {count} | 可造成重大损害 |
| 🟡 M (Medium) | 4.0-6.9 | {count} | 可造成一定损害 |
| 🔵 L (Low) | 0.1-3.9 | {count} | 安全加固建议 |
---
## 3. 上传点映射表
| 序号 | 类名 | 方法 | 上传实现 | 文件名来源 | 保存路径 | 校验状态 | 可利用性 |
|------|------|------|----------|------------|----------|----------|----------|
| 1 | UploadController | upload | MultipartFile | getOriginalFilename | /uploads/ | ❌ 无校验 | ✅ 已确认 |
---
## 4. 高危风险详情
### [{C/H/M/L}-UPLOAD-{序号}] 任意文件上传 / 路径穿越
| 项目 | 信息 |
|------|------|
| 严重等级 | {🔴/🟠/🟡/🔵} {Critical/High/Medium/Low} (CVSS {score}) |
| 可达性 (R) | {0-3} - {判定理由} |
| 影响范围 (I) | {0-3} - {判定理由} |
| 利用复杂度 (C) | {0-3} - {判定理由} |
| 可利用性 | ✅ 已确认 / ⚠️ 待验证 / ❌ 不可利用 |
| 位置 | {Class.method} ({file}:{line}) |
| 上传实现 | {MultipartFile / FileItem} |
#### 校验分析
| 项目 | 值 |
|------|-----|
| 文件名来源 | {getOriginalFilename / item.getName} |
| 目录限制 | {固定/可控} |
| 类型校验 | {白名单/无} |
| Web 可访问 | {是/否} |
| **结论** | {已确认可利用/不可利用/需验证} |
#### 风险点说明
简要描述缺失的校验逻辑与可能的攻击路径。
---
## 5. 反编译文件清单
| 序号 | 原始文件 | 反编译输出路径 |
|------|----------|----------------|
| 1 | UploadController.class | /path/to/decompiled/com/example/UploadController.java |
| 2 | FileStorageService.class | /path/to/decompiled/com/example/FileStorageService.java |
审计检查清单(防遗漏)
代码分析检查
- 所有上传入口已分析(Servlet/MultipartFile)
- 每个上传点均标注文件名来源与保存路径
- 目录与访问控制已分析
反编译检查
- 源码不可用时已反编译
- 反编译文件清单已输出(文件名 + 位置)
报告完整性检查
- 综合审计报告已生成
参考资料
- UPLOAD_RULES.md - 上传实现识别与风险规则
Weekly Installs
2
Repository
ruoji6/java-audit-skillsGitHub Stars
280
First Seen
6 days ago
Security Audits
Installed on
amp2
cline2
opencode2
cursor2
kimi-cli2
codex2