Java反序列化漏洞自动挖掘方法

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Java反序列化漏洞自动挖掘方法

一、序列化与反序列化


1、定义:序列化是用于将对象转换成二进制串存储,对应着 writeObject,反序列正好相反,将二进制串转换成对象,对应着 Freadobject


0a2653c851af460fa595bd959398a8f1.png


2、各编程语言都存在:


Java: java.io.Serializable接口、fastjson、jackson、gson


PHP: serialize()、 unserialize()


Python:pickle


3、使用场景


http参数,cookie,sesion,存储方式可能是base64(rO0),压缩后的base64(H4s),MII等


Servlets http,Sockets,Session管理器,包含的协议就包括:JMX,RMI,JMS,JND1等(\xac\Xed)


xm lXstream,XmldEcoder等(http Body:Content-type: application/xml)


json(jackson,fastjson)http请求中包含



二、Java反序列化过程


1. 对象实例化


sun.misc.Unsafe#allocateInstance


通过反射调用构造函数


0eacb84100b54626af849e6b562bf92a.png


2. 成员变量还原


Setter和getter方法


通过反射直接设置


成员变量的处理(例如:PriorityQueue)


2d65d23f6d4748949b924e4057485923.png


三、Java反序列化漏洞(PriorityQueue)


0a2653c851af460fa595bd959398a8f1.png


四、Java反序列化漏洞挖掘


1、寻找一个类,通过构造一个对象,使其在被反序列化时能执行到危险(sink)方法。


0eacb84100b54626af849e6b562bf92a.png


2、寻找一个类,存在可能的执行路径,从反序 列化入口(source)方法执行到危险(sink)方法自动化搜索)


3、构造这个对象,使危险(sink)方法参数可控。(手工打造)



五、 自动化挖掘实现


1、在静态分析中,这是一个典型的可达性分析问题。


2d65d23f6d4748949b924e4057485923.png


2、 可达性分析 - may分析:无需绘制控制流图,只需搜素调用树。


2e9b90b2ca334476abebe75bafe6eeaa.png


六、、 调用树搜索实现


1、深度优先搜索(DFS) vs 广度优先搜索(BFS)


调用路径越长,payload越难构造 ;搜索深度有限 ;等价于搜索一个n叉树(n>100)的前几层;调用链的存储


0a2653c851af460fa595bd959398a8f1.png


2、深度优先搜索(DFS)


搜索停止条件:到达指定深度;搜索到sink方法


搜索结果保存: 使用stack保存路径


0eacb84100b54626af849e6b562bf92a.png


七、搜索中的多态问题


1、由于面向对象中多态性的存在,只有在运行时 才能确定调用哪个子类的eat方法。


2d65d23f6d4748949b924e4057485923.png


2、多态的处理


构建类、接口和方法继承树(双向树)


寻找调用的方法的实现所在类的所有子类集合


在上述集合中寻找调用者类的子类的集合


这些子类中重写的方法即为所有可能调用的方法


八、路径成环


搜索到CircleChain的hashCode方法时,这个方法调用了Object#hashCode方法,寻找Object的子类会再找到CircleChain


类,形成环。


2e9b90b2ca334476abebe75bafe6eeaa.png


九、路径爆炸


以下方法的实现会造成路径爆炸


1、Java.util.List#get方法


2、Java.lang.Object#toString方法


3、java.util.Iterator#hasNext方法


0a2653c851af460fa595bd959398a8f1.png 0eacb84100b54626af849e6b562bf92a.png


十、路径爆炸成环问题解决


1. 搜索深度限制(兜底)


2. 已搜索方法缓存


1. 先缓存、后搜索


2. 缓存方法signature


4. 调用链缓存


2d65d23f6d4748949b924e4057485923.png


只需要构造C方法执行时的上下文,使其与链2一致即可


十一、Jackson反序列化漏洞挖掘


1、简介


Jackson是一个开源的Java序列化与反序列化工具,可以将java对象序列化为xml或json格式的字符串,或者反序列化回对应的对象,由于其使用简单,速度较快,且不依靠除


JDK外的其他库,被众多用户所使用。


Jackson也是Spring MVC默认的json解析库,打开多态之后,jackson会根据json中传入的类名进行反序列化


相比其他后来开发的json解析库来说,jackson有灵活的API,可以很容易根据需要进行扩展和定制。


2、Jackson历史漏洞


CVE-2017-7525:RCE


CVE-2017-17485:RCE


CVE-2018-14718:RCE


CVE-2019-12086:任意文件读取


CVE-2019-12384:RCE(要求反序列化后再序列化payload)


CVE-2019-14379:RCE (要求反序列化后再序列化)



3、Jackson反序列化过程


对象初始化:


调用类的无参初始化方法


调用包含一个基础类型参数的构造函数,并且这个参数可控


对象中成员变量赋值:


将json看成key-value对,key与field不一定一一对应。


首先看key是否存在setter方法,如果存在setter方法,则会通过反射调用setter方法


否则看在这个类中是否存在与key同名的field,如果存在,则通过反射直接赋值。


否则看是否存在对应的getter方法,且getter的返回值是Collection或者Map的子类,如果满足这个条件,则会调用这个getter方法


如果以上条件都不满足,则抛出异常


0a2653c851af460fa595bd959398a8f1.png


4、反序列化的source method


Jackson反序列化显式调用的方法:仅包含一个基本类型参数的构造函数;Setter方法;返回值是Collection或者Map的子类的getter方法;


反序列化过程中隐式调用的方法:hashCode;compare


5、Jackson反序列化的sink method


命令执行:


• java.lang.reflect.Method#invoke


• javax.naming.Context#lookup


• javax.naming.Context#bind


• java.lang.Runtime#exec


• java.lang.ProcessBuilder#ProcessBuilder


文件读取:


• java.sql.Driver#connect MySQL客户端任意文件读取


• org.xml.sax.XMLReader#parse


• javax.xml.parsers.SAXParser#parse


• javax.xml.parsers.DocumentBuilder#parse


6、Jackson反序列化漏洞搜索结果


CVE-2019-12086:


com.mysql.cj.jdbc.NonRegisteringDriver#connect(String, Properties)-->


com.mysql.cj.jdbc.admin.MiniAdmin#MiniAdmin(String, Properties)-->


com.mysql.cj.jdbc.admin.MiniAdmin#MiniAdmin(String)


CVE-2017-7525:


com.sun.jndi.toolkit.url.GenericURLContext#lookup(String)-->


javax.naming.InitialContext#lookup(String)-->


com.sun.rowset.JdbcRowSetImpl#connect()-->


com.sun.rowset.JdbcRowSetImpl#setAutoCommit(boolean)


javax.xml.parsers.SAXParser#parse(InputSource, DefaultHandler)-->


org.mortbay.xml.XmlParser#parse(InputSource)-->


org.mortbay.xml.XmlConfiguration#XmlConfiguration(String)


CVE-2019-12814


com.sun.xml.internal.fastinfoset.sax.SAXDocumentParser#parse(InputSource)-->


org.apache.xalan.processor.TransformerFactoryImpl#newTemplates(Source)-->


org.jdom.transform.XSLTransformer#XSLTransformer(Source)-->


org.jdom.transform.XSLTransformer#XSLTransformer(String)


禁止非法,后果自负

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
存储 Java 索引
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
|
14天前
|
存储 安全 算法
Java容器及其常用方法汇总
Java Collections框架提供了丰富的接口和实现类,用于管理和操作集合数据。
Java容器及其常用方法汇总
|
16天前
|
存储 缓存 Java
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
59 3
java语言后台管理ruoyi后台管理框架-登录提示“无效的会话,或者会话已过期,请重新登录。”-扩展知识数据库中密码加密的方法-问题如何解决-以及如何重置若依后台管理框架admin密码-优雅草卓伊凡
|
14天前
|
Java API
java.time常用方法汇总
`java.time` API 是从 Java 8 开始引入的时间日期处理库,旨在替代老旧的 `java.util.Date` 和 `Calendar`。它提供了更简洁、强大和灵活的方式处理日期、时间、时区及时间间隔,支持全球化和时间计算需求。API 包含获取当前时间、创建指定时间、解析和格式化字符串、进行加减运算、比较时间、获取年月日时分秒、计算时间间隔、时区转换以及判断闰年等功能。示例代码展示了如何使用这些功能,极大简化了开发中的时间处理任务。
|
1月前
|
Java
Java快速入门之类、对象、方法
本文简要介绍了Java快速入门中的类、对象和方法。首先,解释了类和对象的概念,类是对象的抽象,对象是类的具体实例。接着,阐述了类的定义和组成,包括属性和行为,并展示了如何创建和使用对象。然后,讨论了成员变量与局部变量的区别,强调了封装的重要性,通过`private`关键字隐藏数据并提供`get/set`方法访问。最后,介绍了构造方法的定义和重载,以及标准类的制作规范,帮助初学者理解如何构建完整的Java类。
|
1月前
|
Java 程序员 调度
Java 高级面试技巧:yield() 与 sleep() 方法的使用场景和区别
本文详细解析了 Java 中 `Thread` 类的 `yield()` 和 `sleep()` 方法,解释了它们的作用、区别及为什么是静态方法。`yield()` 让当前线程释放 CPU 时间片,给其他同等优先级线程运行机会,但不保证暂停;`sleep()` 则让线程进入休眠状态,指定时间后继续执行。两者都是静态方法,因为它们影响线程调度机制而非单一线程行为。这些知识点在面试中常被提及,掌握它们有助于更好地应对多线程编程问题。
66 9
|
1月前
|
安全 Java 程序员
Java面试必问!run() 和 start() 方法到底有啥区别?
在多线程编程中,run和 start方法常常让开发者感到困惑。为什么调用 start 才能启动线程,而直接调用 run只是普通方法调用?这篇文章将通过一个简单的例子,详细解析这两者的区别,帮助你在面试中脱颖而出,理解多线程背后的机制和原理。
68 12
|
1月前
|
算法 Java API
Java 方法注释:规范、实用和高质量的写法
本文深入探讨了如何编写高质量的 Java 方法注释
72 11
|
1月前
|
SQL Java 数据库连接
【潜意识Java】Java中JDBC过时方法的替代方案以及JDBC为什么过时详细分析
本文介绍了JDBC中一些常见过时方法及其替代方案。
44 5
|
3月前
|
Java 数据处理 数据安全/隐私保护
Java处理数据接口方法
Java处理数据接口方法
38 1

热门文章

最新文章