Java 反序列化多态攻击面静态扫描器 + 利用面确证沙箱 + 默认配置安全基线 一套把「侦察 → 研判 → 打击」三段式反序列化挖掘方法论工程化的完整交付件。
deser-radar 在海量 Java 源码里几秒钟定位「不可信输入 + 默认/宽松配置下类型名可控的反序列化用法」这类 RCE 高危攻击面,作为人工代码审计的侦察雷达缩小审计范围;并配套一个隔离沙箱,用真实发布库的默认配置实证这些攻击面一旦暴露的确定危害。
本项目是防御导向的安全研究工具,用于授权范围内的安全评估、代码审计与安全教育。
- 扫描器只做静态特征识别,不发起任何网络攻击。
- 沙箱中的靶机 / 攻击客户端 / gadget 载荷仅用于隔离环境的利用面确证,请勿指向任何未获授权的系统。
- 使用者须遵守所在司法辖区法律。因滥用造成的一切后果由使用者自负,作者不承担任何责任。
DeserRadar/
├── scanner/ # ① 侦察:静态攻击面扫描器
│ ├── deser_radar.py # 核心扫描器(零依赖,Python3 标准库)
│ └── test_deser_radar.py # 回归测试套件(13 用例,黑盒 golden-file)
├── sandbox/ # ③ 打击:利用面确证沙箱(by-design 靶机)
│ ├── Dockerfile # JDK8 基础镜像(eclipse-temurin:8-jdk)
│ ├── docker-compose.yml # 一键 build+run+attack+采证
│ ├── entrypoint.sh # 容器内编译→起靶机→打攻击→落证据
│ ├── ExploitTarget.java # 多端口反序列化靶机(HTTP + raw socket + JNDI 捕获)
│ ├── Attack.java # 攻击客户端(六库真实 gadget 载荷)
│ ├── evil/ # SnakeYAML 自包含 RCE 用恶意 ScriptEngineFactory
│ ├── run.sh # 本地 JVM 直跑版(不依赖 Docker)
│ └── fetch-libs.sh # 从 ~/.m2 补齐 13 个真实库 jar
├── docs/ # 研究文档
│ ├── 反序列化默认配置安全基线.md # 可交付客户的七库安全基线 v1.0
│ └── AI-Agent反序列化攻击面研究白皮书.md # 完整研究白皮书(含三段式方法论)
├── README.md
├── ROADMAP_v2.md # 扫描器 v2 路线图
└── LICENSE # MIT
核心定位:它标出「哪些文件用了危险的默认反序列化用法」,把人工审计范围从整个仓库缩到几行代码。它不判断数据流是否真被外部输入触达、classpath 有没有 gadget——那是人工研判 + 动态实证的事。
| 库 | 危险特征 | 安全写法(不报) |
|---|---|---|
| Jackson | enableDefaultTyping/activateDefaultTyping + readValue(.., Object/Map.class) |
强类型 POJO / 禁用多态 |
| Kryo | new Kryo() + 无参 readObject / readClassAndObject |
readObject(X.class) 强类型 |
| FST | FSTConfiguration + 无参 readObject |
readObject(X.class) 强类型 |
| Hessian2 | new Hessian2Input / Hessian2ObjectInput 等封装 + 无参 readObject |
readObject(X.class) 强类型 |
| SnakeYAML | 无参 new Yaml() + load |
new Yaml(new SafeConstructor()) |
| XStream | new XStream() + fromXML/fromJSON |
已 setupDefaultSecurity/allowTypes |
MCP 上下文(McpServer / @Tool / tools/call / ToolCallback)同现时升级为 HIGH(攻击者可经 tools/call.arguments 直达)。
零第三方依赖,Python 3.8+ 即可:
# 扫描目录(递归 .java)或单文件,默认人类可读摘要
python3 scanner/deser_radar.py <path>
# 机器可读输出
python3 scanner/deser_radar.py <path> --json # JSON
python3 scanner/deser_radar.py <path> --sarif # SARIF 2.1.0(接 GitHub code scanning)
python3 scanner/deser_radar.py <path> --simple # 每行一条精简
# CI 门禁:命中 MEDIUM(或更高)即非零退出,阻断合并
# 推荐用 MEDIUM —— 绝大多数真实危险用法被判定为 MEDIUM;
# HIGH 仅在「MCP/Agent 上下文」同现时才升级,普通仓库用 HIGH 会漏掉绝大多数问题
python3 scanner/deser_radar.py <path> --fail-on MEDIUM
# 排除路径(默认已跳过 test/target/build/.git/node_modules 等;传 NONE 关闭默认排除)
python3 scanner/deser_radar.py <path> --exclude "samples/,examples/"
### 示例输出
扫描一个含危险 Jackson 用法的文件(`enableDefaultTyping` + `readValue(.., Object.class)`),默认摘要输出形如:
```text
[*] 扫描 Java 文件: 1 命中: 1
========================================================================
[MEDIUM] /path/to/Sample.java
原因: 全局 ObjectMapper 开启 default typing,属 Jackson 通用 RCE 面;若用于解析外部/不可信 JSON(含 MCP arguments)则可达 RCE
L6: ... om.enableDefaultTyping(); om.readValue(json, Object.class); ...
[修复建议] 移除全局 ObjectMapper 的 default typing(多态反序列化)……
[安全替代写法]:
ObjectMapper mapper = new ObjectMapper();
// 不要调用 activateDefaultTyping / enableDefaultTyping
========================================================================
通用修复原则:
1. 全局 ObjectMapper 严禁 enableDefaultTyping / activateDefaultTyping;
2. 如需多态,改用 activateDefaultTyping + 严格 PolymorphicTypeValidator 白名单;
...每条命中都会给出原因 + 命中代码行 + 修复建议 + 可直接抄的安全替代写法。注意:扫描器只标出「危险用法在哪」,不判定数据流是否真被外部输入触达、classpath 有无 gadget——那是人工研判(三段式第二阶段)的事。
### 回归测试
```bash
python3 scanner/test_deser_radar.py
# 结果: 13 passed, 0 failed, total 13
13 个 golden-file 黑盒用例锁定「三类误报/漏报修复不回归 + 六库默认危险入口仍命中」,安全代码零误报。
- name: DeserRadar SAST
run: |
python3 scanner/deser_radar.py . --sarif > deser-radar.sarif
python3 scanner/deser_radar.py . --fail-on HIGH
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: deser-radar.sarif回答「这些攻击面一旦暴露,危害到底有多确定」。用 ~/.m2 里真实发布的库 jar、全走库作者默认用法,对外暴露多个反序列化端口,再从外部端口打真实 gadget 载荷,采集 RCE / 类型控制证据。
装了什么:JDK8 镜像 + 13 个真实库 jar + 靶机 ExploitTarget(HTTP 18080 收 yaml/xstream/json、hessian2 18081、kryo 18082、fst 18083、JNDI 捕获 1389)+ 攻击客户端 Attack + 恶意 evil.jar。
⚠️ 前置要求:第三方 jar 不随仓库发布。本仓库通过.gitignore排除所有第三方 jar,运行沙箱前必须先拿到 13 个真实库 jar(完整清单见sandbox/fetch-libs.sh顶部JARS数组,含snakeyaml-1.30、xstream-1.4.11、hessian-lite-4.0.3、kryo-5.5.0、jackson-databind-2.9.10、fst-2.57等)。两种方式:
- 本地已有 Maven 仓库
~/.m2:直接bash sandbox/fetch-libs.sh,脚本自动从~/.m2收集 13 个 jar 到sandbox/libs/。- 本地没有
~/.m2/ 缺少某些库:用mvn dependency:get -Dartifact=<groupId:artifactId:version>(坐标见fetch-libs.sh)拉取,或手动下载对应 jar 放到sandbox/libs/。 缺 jar 时docker compose up --build会失败或靶机编译报错。
一键运行(Docker):
bash sandbox/fetch-libs.sh # 先从本地 m2 补齐 13 jar
cd sandbox && docker compose up --build --abort-on-container-exit
# 证据落到 sandbox/evidence/(rce_yml = SnakeYAML 自包含 RCE 跨容器落盘铁证)本地 JVM 直跑(不依赖 Docker,需 JDK11+):cd sandbox && bash run.sh
实证结论(隔离环境):
- 🔴 SnakeYAML 1.30 默认
new Yaml():外部 YAML → 完整自包含 RCE(ScriptEngineManager链)。 - 🟠 Hessian2 / Kryo / FST / Jackson:外部输入可控制反序列化实例化的类名(RCE 必要前提,完整链取决于目标 classpath gadget)。
- 🟡 XStream 1.4.11 默认配置纵深防御:黑名单挡经典
EventHandler链;JdbcRowSetImpl虽不在黑名单但被 SerializableConverter 拦——两条最经典链默认均不可达(正向防御结论)。
⚠️ 沙箱是 by-design 靶机,证明「默认配置一旦暴露危害确定」,不是真实靶标的漏洞。
| 阶段 | 主体 | 工具 | 军事类比 |
|---|---|---|---|
| 侦察 | 扫描器 | scanner/deser_radar.py |
雷达扫出光点 |
| 研判 | 人(代码审计) | 确认 sink 是否被外部输入真实触达 / trust boundary / gadget | 飞行员目视辨敌我 |
| 打击 | 动态沙箱 | sandbox/ |
开火命中 |
扫描器扫不出 0day,0day 是人挖的——工具缩小范围、人工审计发现漏洞、动态沙箱确证利用,三者缺一不可。详见 docs/ 白皮书。
- 《反序列化默认配置安全基线》v1.0:七库默认危险度矩阵 + 可直接抄的加固代码 + 检查清单 + P0-P3 修复 SLA,面向客户交付。
- 《AI-Agent 反序列化攻击面研究白皮书》:完整研究记录,含扫描器规则、三段式方法论、动态实证与诚实边界。
MIT © 2026 joysinleung