JDK7u21反序列化漏洞分析

Zachary 后端开发 20744

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 the
fields, methods and constructors of loaded classes, and to use
reflected fields, methods, and constructors to operate on their
underlying 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对象去执行系统命令,这就可能导致远程命令执行漏洞。

回复

我来回复
  • 暂无回复内容

扫码关注
扫码关注
分享本页
返回顶部