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.png0eacb84100b54626af849e6b562bf92a.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)


禁止非法,后果自负


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
28 4
|
14天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
35 17
|
9天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
40 5
|
7天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
13 2
|
13天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
9天前
|
Java Spring
JAVA获取重定向地址URL的两种方法
【10月更文挑战第17天】本文介绍了两种在Java中获取HTTP响应头中的Location字段的方法:一种是使用HttpURLConnection,另一种是使用Spring的RestTemplate。通过设置连接超时和禁用自动重定向,确保请求按预期执行。此外,还提供了一个自定义的`NoRedirectSimpleClientHttpRequestFactory`类,用于禁用RestTemplate的自动重定向功能。
|
13天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
10 0
|
10天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
1天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
15 1