Panda | 热爱安全的理想少年 - 反序列化
type: channel
link: https://www.cnpanda.net/tag/反序列化/
items: 用一个 case 去理解 jdk8u20 原生反序列化漏洞
items: JDK7u21反序列化漏洞分析笔记

用一个 case 去理解 jdk8u20 原生反序列化漏洞
type: item
date: 2021-06-30T04:42:00+00:00
description: 0x01 写在前面jdk8u20原生反序列化漏洞是一个非常经典的漏洞，也是我分析过最复杂的漏洞之一。在这个漏洞里利用了大量的底层的基础知识，同时也要求读者对反序列化的流程、序列化的数据结构有一定的了解本文结合笔者自身对该漏洞的了解，写下此文，如有描述不当或者错误之处，还望各位师傅指出0x02 jdk8u20 漏洞原理jdk8u20其实是对jdk7u21漏洞的绕过，在《JDK7u21反序列化漏洞分析笔记》 一文的最后我提到了jdk7u21的修复方式：首先来看存在漏洞的最后一个版本（611bcd930ed1）：http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/611bcd930ed1/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java查看其 children 版本（0ca6cbe3f350）：http://hg.openjdk.java.net/jdk7u/jdk7u/jdk/file/0ca6cbe3f350/src/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.javacompare一下：// 改之前 AnnotationType annotationType = null; try { annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; all bets are off return; } // 改之后 AnnotationType annotationType = null; try { annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; time to punch out throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream"); }可以发现，在第一次的修复中，官方采用的方法是网上的第二种讨论，即将以前的 return 改成了抛出异常。我们来看第一次修复后的AnnotationInvocationHandler.readObejct()方法：private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // Check to make sure that types have not evolved incompatibly AnnotationType annotationType = null; try { annotationType = AnnotationType.getInstance(type); } catch(IllegalArgumentException e) { // Class is no longer an annotation type; time to punch out throw new java.io.InvalidObjectException("Non-annotation type in annotation serial stream"); } Map<String, Class<?>> memberTypes = annotationType.memberTypes(); // If there are annotation members without values, that // situation is handled by the invoke method. for (Map.Entry<String, Object> memberValue : memberValues.entrySet()) { String name = memberValue.getKey(); Class<?> memberType = memberTypes.get(name); if (memberType != null) { …

JDK7u21反序列化漏洞分析笔记
type: item
date: 2021-06-10T15:06:00+00:00
description: 目录目录0x01 写在前面0x02 所需的知识点0x03 基础知识1、Java 反射2、javassist 动态修改类3、Java 静态类加载4、Java 动态代理Proxy 类InvocationHandler 接口5、hash碰撞0x04 jdk7u21 payload0x05 漏洞分析0x06 漏洞修复0x07 总结0x08 参考0x01 写在前面JDK7u21原生gadget链的构造十分经典，在对于其构造及思想学习后，写下本文作为笔记。0x02 所需的知识点JDK7u21这个链用了很多的Java基础知识点，主要如下：Java 反射javassist 动态修改类Java 静态类加载Java 动态代理hash碰撞为了方便大家理解此文，因此我会对这些知识点进行简单介绍，如果都了解的朋友可以直接翻到后面的分析过程。0x03 基础知识1、Java 反射反射 (Reflection) 是 Java 的特征之一，在C/C++中是没有反射的，反射的存在使得运行中的 Java 程序能够获取自身的信息，并且可以操作类或对象的内部属性。那么什么是反射呢？对此， Oracle 官方有着相关解释：“Reflection enables Java code to discover information about thefields, methods and constructors of loaded classes, and to usereflected fields, methods, and constructors to operate on theirunderlying counterparts, within security restrictions.”（反射使Java代码能够发现有关已加载类的字段、方法和构造函数的信息，并在安全限制内使用反射的字段、方法和构造函数对其底层对应的对象进行操作。）简单来说，通过反射，我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。同样的，JAVA的反射机制也是如此，在运行状态中，通过 Java 的反射机制，对于任意一个类，我们都能够判断一个对象所属的类；对于任意一个类，都能够知道这个类的所有属性和方法；对于任意一个对象，都能够调用它的任意一个方法和属性；这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。既然利用Java的反射机制，我们可以无视类方法、变量访问权限修饰符，可以调用任何类的任意方法、访问并修改成员变量值，那么这可能导致安全问题，如果一个攻击者能够通过应用程序创建意外的控制流路径，那么就有可能绕过安全检查发起相关攻击。假设有段代码如下： String name = request.getParameter("name"); Command command = null; if (name.equals("Delect")) { command = new DelectCommand(); } else if (ctl.equals("Add")) { command = new AddCommand(); } else { ... } command.doAction(request);存在一个字段为name，当获取用户请求的name字段后进行判断，如果请求的是 Delect 操作，则执行DelectCommand 函数，若执行的是 Add 操作，则执行 AddCommand 函数，如果不是这两种操作，则执行其他代码。此时，假如有位开发者看到了这段代码，他觉得可以使用Java 的反射来重构此代码以减少代码行，如下所示：String name = request.getParameter("name"); Class ComandClass = Class.forName(name + "Command"); Command command = (Command) CommandClass.newInstance(); command.doAction(request);这样的重构看起来使得代码行减少，消除了if/else块，而且可以在不修改命令分派器的情况下添加新的命令类型，但是如果没有对传入进来的name字段进行限制，那么我们就能实例化实现Command接口的任何对象，从而导致安全问题。实际上，攻击者甚至不局限于本例中的Command接口对象，而是使用任何其他对象来实现，如调用系统中任何对象的默认构造函数，再如调用Runtime对象去执行系统命令，这就可能导致远程命令执行漏洞。更多关于反射的内容具体可以参考我以前写的这篇文章：https://www.cnpanda.net/codeaudit/705.html2、javassist 动态修改类…