fastjson及其反序列化分析--TemplatesImpl

# fastjson及其反序列化分析


源码取自
https://www.github.com/ZH3FENG/PoCs-fastjson1241

参考
(23条消息) Json详解以及fastjson使用教程_srj1095530512的博客-CSDN博客_fastjson

parse方法和parseObject方法区别:

	parse()及parseObject()进行反序列化时的细节区别在于,parse() 会识别并调用目标类的 setter 方法,而 parseObject() 由于要将返回值转化为JSONObject,多执行了 JSON.toJSON(obj),所以在处理过程中会调用反序列化目标类的getter 方法来将参数赋值给JSONObject

ParserConfig类:配置反序列化信息

Autotype:

​ Fastjson提供了autotype功能,允许用户在反序列化数据中通过“@type”指定反序列化的Class类型。

AutoType安全校验
知道了AutoType的作用后,假设如下场景,

​ 服务端接收到的请求Json串中包含了指定恶意代码Class的@Type,
​ 服务端调用JSON.parseObject()时触发了该Class中的构造函数、或者是getter、setter方法中的恶意代码

AutoType黑名单机制:在反序列化时,会校验指定的class是否在黑名单中,若在,则抛出异常

Safemode机制:配置safeMode后,无论白名单和黑名单,都不支持autoType,可一定程度上缓解反序列化Gadgets类变种攻击。

TemplatesImpl 利用链

fastjson反序列化TemplatesImpl - Afant1 - 博客园 (cnblogs.com)

在fastjson中调用Templateslmpl可以构造一条反序列化攻击链。

攻击链分析

TemplatesImpl攻击调用链路
com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl是历史上出现过存在FastJson反序列漏洞的一个第三方类

TemplatesImpl中存在一个get方法为getOutputProperties(),其在调用FastJson.parseObject()序列化为Java对象时会被调用
getOutputProperties内部调用了newTransformer()方法,newTransformer()内部调用了getTransletInstance()方法获取Translet对象
获取Translet对象时,其通过内部的私有变量_bytecodes生成返回的Translet对象
这里这个_bytecodes私有变量就是整个攻击设计的核心所在,虽然FastJson默认只能反序列化公有属性,但是可以在JSON串中指定_bytecodes为我们恶意攻击类的字节码,同时调用JSON.parseObject(json, Object.class, Feature.SupportNonPublicField)来反序列化私有属性,那么_bytecodes就可以是任意指定代码

也就是说,如果事先定义好了Translet返回Class类的内容,并且在自定义的Translet类的构造函数中实现攻击代码,并且把攻击代码转化成字节码,传入TemplatesImpl的私有变量_bytecodes中,那么反序列化生成TemplatesImpl时就会使用我们自定义的字节码来生成Translet类,从而触发Translet构造函数中的攻击代码

​ 首先使用parseObject对payload进行反序列化。parseObject会调用payload中存储的@type信息,即Templateslmpl的getter,setter,和构造方法。

在TypeUtil.class中下断点,此处加载Templateslmpl类。

这里调用了getter方法,getOutputProperties

调用newTransformer方法

调用getTransletInstance方法

这里会调用defineTransletClasses,通过传入的_bytecodes生成 _class

此处可以看到成功传入类名,调用newInstance实例化为tranlet对象

此处调用恶意构造方法

完整的利用链

payload构造分析

 String payload = "{\"@type\":\"" + NASTY_CLASS +
     "\",\"_bytecodes\":[\""+evilCode+"\"],'_name':'a.b','_tfactory':{ },\"_transletIndex\":0,\"_auxClasses\":{},\"_outputProperties\":{}}";

这里NASTY_CLASS是指要加载的类,这里evilCode时包含恶意代码的类路径,需要使用字节码在进行base64编码。getTransletInstance方法中会判断_name是否为空,因此这里需要设置 _name字段。

 public static String readClass(String cls){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            IOUtils.copy(new FileInputStream(new File(cls)), bos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return Base64.encodeBase64String(bos.toByteArray());
    }

这里对整个_bytecodes部分做了base64解码,所以payload要进行base64编码

JdbcRowSetImpl利用链

fastjson反序列化JdbcRowSetImpl - Afant1 - 博客园 (cnblogs.com)
待更新

posted @ 2021-10-10 19:41  xyylll  阅读(829)  评论(0编辑  收藏  举报