Skip to main content

java-file-chain-audit

审计 Java 上传/下载/删除链(.jsp RCE 判定、physicalPath 穿越)。

설치로 이동

소스 정보

저장소
Kur1sulab/whitebox
최근 소스 활동
2026년 8월 12일 15:06
감지된 SKILL.md 언어
중국어
스타
1
포크
0

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
2 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
java-file-chain-audit
description
审计 Java 上传/下载/删除链(.jsp RCE 判定、physicalPath 穿越)。
version
1.0.0
author
hermes-curator
license
MIT
metadata
{"hermes":{"tags":["pentest","java","whitebox","file-upload","path-traversal","jeecgboot"],"related_skills":["java-web-framework-pentest","path-traversal-lfi"]}}
# Java Web 文件操作链白盒审计(上传→落盘→读取/删除) > 实战固化:zsk kykms(JeecgBoot 2.4.5 二开)路3 文件链深挖,全部方法经本地源码验证。会话细节与证据见 `references/kykms-route3.md`。 ## When to Use - 拿到 Java 二开源码(JeecgBoot/SpringBoot/RuoYi 系)要审计上传/下载/删除链、判定"上传能否 getshell"、找任意文件读/删原语时加载。 - 触发词:白盒审计、文件上传链、.jsp 落盘、getFileSuffix、physicalPath、convertPdf/soffice 命令拼接、uploadDoc 匿名写盘。 ## 0. 工作流 1. **部署形态先定罪**(决定 .jsp 落盘 RCE 生死,最优先) 2. 还原落盘全链(配置源 → 目录 → 文件名 → DB 记录) 3. 枚举 physicalPath / 路径参数的每个 sink 与每个可控入口 4. 分析后缀提取 sink 的可达字符集(结构性快判) 5. 命令执行点二分(ProcessBuilder vs Runtime.exec) 6. 输出中文报告:每条候选带【推演】+ 成立条件 + 四级置信度(★★★★高/★★★中/★★低/★极低)+ 文件:行号证据索引 ## 1. 部署形态先定罪(.jsp 落盘 RCE 成立与否的前提) - 查 docker-compose/Dockerfile/启动脚本:`java -jar xxx.jar` = **fat jar 内嵌 Tomcat** → 无 webapps 解析目录,.jsp 落盘 ≠ RCE;外部 Tomcat WAR 部署且 uploadDir 落入 webapps 内才可执行。 - 查 yml `spring.resource.static-locations` 仅 classpath(`classpath:/static/,classpath:/public/`)= 无磁盘静态映射;grep `addResourceHandlers|ResourceHandlerRegistry|file:` 全库 0 命中 = 上传目录不可 URL 直达。 - 下载/预览端点若 `application/octet-stream` + attachment 字节流输出 = 即使读得到也不执行 JSP。 - **死亡判定三件套**(全中即 .jsp RCE 不成立,改走"认证任意文件读/删"链): ① uploadDir 在 webroot/nginx alias 外 ②无静态映射 ③无 JspServlet。 - 真实判定法:登录后 list 端点看 physicalPath 前缀是否含 webapps 路径。 - 源码 dump 常无 pom.xml/build 文件 → 依赖版本只能标★低置信,别硬猜。 ## 2. 落盘全链还原模板 ``` Controller.upload (入口/权限) └─ 白名单校验 isFileTypeSupport(suffix) ← 查是否 DB 配置,空→return true 全放行 = 真绕过点 └─ saveFile(file) ├─ todayDir = new File(uploadDir, "yyyyMMdd") + mkdirs ├─ fileId = UUID(不可预测) ├─ suffix = getFileSuffix(originalFilename) ← 唯一可控片段 ├─ dist = new File(todayDir, fileId + "." + suffix); transferTo(dist) ← 已写盘 └─ physicalPath = getRelativePath(dist)(存 DB,含前导 /) └─ 下游业务方法(常因 sysUser NPE 抛错) ``` ## 3. 后缀提取 sink(getFileSuffix 类)结构性快判 `lastIndexOf(".")` 截尾 + toLowerCase: - **后缀内结构性不可能含 "."**(分割点即最后一个点)→ `../` 穿越、双后缀、空字节在后缀内**不可达**,别浪费时间试。 - 后缀可含 "/" 与任意非点字符 → 目录注入(`a.jsp/x` → todayDir/UUID.jsp/x 建子目录),无越界。 - 大小写:双方都 toLowerCase 时无大小写绕过面。 - 真正的"后缀绕过" = 白名单从 DB 配置读、配置为空 `return true` 全放行——这才是报告成立点。 ## 4. physicalPath 存库 = 穿越放大器(Java 特有语义) - **`new File(uploadDir, child)` 中 child 以 "/" 开头时 parent 被忽略**,直指文件系统根 → 正常代码即错位(uploadDir="/" 才正确),同时放大删除/读取面。审计 delete/read sink 必查此语义。 - 拼接点无净化(`uploadDir + "/" + relativePath` 直拼)→ 存库 physicalPath 含 `../../` 即穿越;`getRelativePath` 类前缀校验是纯字符串比较无规范化,`/up/dir/../../etc/passwd` 可通过校验。 - **可控入口枚举**(按可达性排序): 1. 通用 CRUD 控制器的 `PUT /xxx/edit`(@RequestBody 实体 + 无 @RequiresPermissions,仅登录)改任意行任意字段 = physicalPath 完全可控(JeecgBoot 系标配) 2. `POST /xxx/add`(自造 id + 任意字段) 3. 匿名上传接口(只能生成服务端路径,不能直接控 physicalPath,但可改引用关系) 4. 服务端内部调用(不可控,标注即可) - **标准任意文件读链**:匿名注册(/sys/user/register)→ 登录 → list 拿 id(doc 的 fileId/previewFileId 经 list/queryById 可枚举)→ edit physicalPath=../../../etc/passwd → preview/download 端点(FileInputStream 直拼无净化)穿越读 → 提取配置 DB/Redis 口令 → 横向 RCE。 - **标准任意文件删链**:同上 edit physicalPath → delete 端点(无状态/归属校验时)→ deleteKmFile 类 `new File(uploadDir, physicalPath).delete()` 穿越删(绝对 child 语义下前导 / 直指根路径文件)。 ## 5. 写盘先于业务校验/异常(匿名持久化原语) - `saveFile`(transferTo + INSERT)先执行,下游业务方法因 sysUser NPE 等抛错时文件已落盘,清理代码只在窄分支(如 `kmDoc!=null && id==null`)→ **匿名上传持久化实锤**。 - 审计盯"transferTo 与后续校验/事务的先后顺序";NPE 路径不触发清理 = 报告高光成立点。 ## 6. 命令执行 Java 二分 - `ProcessBuilder(List)` = 无 shell 无注入(参数数组化,文件名含 `$()`/`;`/空格均安全)→ 别报"命令注入"。 - `Runtime.exec("cmd /c ...")` 字符串拼接 = 仅 Windows 生效(Linux 无 cmd 直接失败)→ 目标 Linux 时此面直接标注不适用。 - LibreOffice 转换(soffice --convert-to pdf)触发面 = 匿名上传 docx/xls 即喂攻击者文件给解析器 → 命令注入无,解析 RCE 依赖具体 CVE(★低,别当主线)。 ## 7. 解析器/Tika 审计点 - `BodyContentHandler(Integer.MAX_VALUE)` = 无写入上限 → zip bomb/超大文件 OOM **DoS**(需认证触发点时标注认证前置)。 - Tika OOXML XXE(CVE-2019-10088 类)依赖版本且需 OOB 外带 → ★极低。 - 无 pom 时版本区间按框架年代估(JeecgBoot 2.4.x ≈ 2021-2022 → tika 1.24-1.28),标★低置信。 ## 8. ShiroConfig anon 清单速览(JeecgBoot 系) - `/**/*.html|js|css|pdf|jpg|png|ico` 全匿名是标配 → 配合任何磁盘→URL 映射(nginx alias / 资源处理器)会放大存储型 XSS。 - `/onlyoffice/**` 类 anon 指向**不存在控制器** = 死配置(落静态资源 404)→ 报告写"残留配置",别当攻击面。 - sha256 去重接口报错泄露 originalName = 文件存在性哈希预言机(低危信息泄露)。 ## 9. 报告格式约定(本用户偏好) - 中文,证据带 `文件:行号`,每条候选带【推演】+ 成立条件。 - 四级置信度:★★★★高 / ★★★中 / ★★低 / ★极低;默认配置下的结论与"偏离默认才成立"的条件分开写。 - 结论先行("RCE 成立/不成立"一句话),再给证据表。 - 产出去 `D:\tools\audit\<项目>\audit\<route>-<主题>.md`。
GitHub에서 보기