Java反射机制&类对象&成员方法&构造方法&攻击链

发布时间:2023年12月20日

目录

0x00 前言

0x01 Java 反射介绍

0x02 利用反射获取 Class 对象类

0x03 利用反射获取 Field 成员变量类

0x04 利用反射获取 Method 成员方法类

0x05 利用反射获取 Constructor 构造方法类

0x06 Java-反射-不安全命令执行&反序列化链构造


0x00 前言

希望和各位大佬一起学习,如果文章内容有错请多多指正,谢谢!?

个人博客链接:CH4SER的个人BLOG – Welcome To Ch4ser's Blog

0x01 Java 反射介绍

1、什么是 Java 反射

参考:JAVA安全基础(二)-- 反射机制 - 先知社区 (aliyun.com)

Java 反射是一种强大的机制,它可以在运行时动态地获取和操作类的信息。通过反射,我们可以实现一些动态的功能,并且可以更灵活地使用和扩展已有的类。片面的来讲,对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制

?

  • Java 提供了一套反射API,该 API 由 Class 类与 java.lang.reflect 类库组成,该类库包含了Field、Method、Constructor等类
  • 对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制
  • Java 反射是一种机制,它允许我们在运行时(非编译时)动态地获取一个类的信息并操作它。通过反射,我们可以在不知道类的具体细节的情况下,获取类的成员变量、成员方法和构造方法,并且可以在运行时动态地创建对象、调用方法、访问属性等操作。
  • 在 Java 中,每个类在编译后都会生成一个对应的 .class 文件。当我们使用 Java 编译器(javac)编译一个类文件时,会生成一个 .class 文件,并且 JVM 会自动加载这个 .class 文件到内存中。同时,JVM 会为每个类创建一个 Class 对象,这个 Class 对象包含了类的所有信息,包括成员变量、成员方法和构造方法等。
  • 通过反射,我们可以获取一个类的 Class 对象,然后使用 Class 对象中提供的方法来获取类的成员变量、成员方法和构造方法等信息。例如,我们可以通过 Class 对象的getField 方法来获取类的公共成员变量,通过 getMethod 方法来获取类的公共成员方法,通过 getConstructor 方法来获取类的公共构造方法等。
  • 通过获取类的成员变量、成员方法和构造方法等信息,我们可以在运行时动态地创建对象、调用方法、访问属性等操作。这使得我们能够更灵活地使用和扩展已有的类,实现一些动态的功能。

因此,Java 的反射机制与我们之前了解的 Java 运行体系没有太大区别。唯一的区别是在我们生成 .class 文件的同时,也会创建一个 Class 对象。Class 对象是所有类的类,而所有的类本身则是 Class 对象的实例。因此,反射机制并不复杂,它的核心就是获取一个类的 Class 对象,然后使用 Class 对象提供的方法来获取成员变量、成员方法和构造方法等信息,进而动态地获取一个类的属性、变量、构造方法等,并进行操作。简而言之,反射机制就是通过获取 Class 对象来实现动态获取和操作类的信息

2、为什么要用到反射

能够在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象的具体细节。

划重点:在运行时而不是编译时。(不改变原有代码逻辑,运行的时候动态创建和编译即可)

这里补充一下 Java 的编译机制:

  • 静态编译:在编译时确定好类型,绑定对象
  • 动态编译:在运行时确定好类型,绑定对象

3、反射在安全的应用场景

  • 造利用链,触发命令执行
  • 反序列化中的利用链构造
  • 动态获取或执行任意类中的属性或方法
  • 动态代理的底层原理是反射技术
  • rmi 反序列化也涉及到反射操作

0x02 利用反射获取 Class 对象类

首先创建一个 User 类,有成员变量、构造方法、成员方法,如下:

?

然后,获取 Class 对象,有以下这四种方法:

//1、根据类名:类名.class
Class userClass = User.class;
//2、根据对象:对象.getClass()
User user = new User();
Class aClass = user.getClass();
//3、根据全限定类名:Class.forName("全路径类名")
Class aClass1 = Class.forName("com.example.reflectdemo.User");
//4、通过类加载器获得Class对象://ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader clsload=ClassLoader.getSystemClassLoader();
Class aClass2 = clsload.loadClass("com.example.reflectdemo.User");

?

0x03 利用反射获取 Field 成员变量类

1、Class类中用于获取成员变量的方法
Field[] getFields(): 返回所有公共成员变量对象的数组(即所有public)
Field[] getDeclaredFields(): 返回所有成员变量对象的数组(即所有public、protected、private)
Field getField(String name): 返回单个公共成员变量对象(即单个public)
Field getDeclaredField(String name): 返回单个成员变量对象(即单个public、protected、private)

2、成员变量赋值和获取值方法
void set(Object obj, Object value): 赋值
Object get(Object obj): 获取值

?

0x04 利用反射获取 Method 成员方法类

1、Class类中用于获取成员方法的方法
Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>...parameterTypes): 返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>...parameterTypes): 返回单个成员方法对象

2、Method类中用于创建对象的方法
Object invoke(Object obj, Object...args): 运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)

?

0x05 利用反射获取 Constructor 构造方法类

1、Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors(): 返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors(): 返回所有构造方法对象的数组
Constructor<T> getConstructor(Class<?>... parameterTypes): 返回单个公共构造方法对象
Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 返回单个构造方法对象

2、Constructor类中用于创建对象的方法
T newInstance(Object... initargs): 根据指定的构造方法创建对象
setAccessible(boolean flag): 设置为true,表示取消访问检查

?

0x06 Java-反射-不安全命令执行&反序列化链构造

1、举例-反射实现命令执行

-原型:
Runtime.getRuntime().exec("calc");
-反射:
//方法1:
Class aClass = Class.forName("java.lang.Runtime");
//获取所有公共包括继承的成员方法
Method[] methods = aClass.getMethods();
for (Method me:methods){
    System.out.println(me);
}
//获取exec成员方法
Method exec = aClass.getMethod("exec", String.class);
//获取getRuntime成员方法
Method getRuntimeMethod = aClass.getMethod("getRuntime");
//执行
Object runtime = getRuntimeMethod.invoke(aClass);
exec.invoke(runtime, "calc.exe");

//方法2:
Class c1= Class.forName("java.lang.Runtime");
Constructor m = c1.getDeclaredConstructor();
m.setAccessible(true);
c1.getMethod("exec", String.class).invoke(m.newInstance(), "calc");

2、不安全的反射对象

指应用程序使用具有反射功能的外部输入来选择要使用的类或代码,可能被攻击者利用而输入或选择不正确的类,绕过身份验证或访问控制检查。

参考分析:悟空云课堂 | 第七期:不安全的反射漏洞 - 知乎 (zhihu.com)

利用结合:JAVA反序列化 - Commons-Collections组件 - 先知社区 (aliyun.com)

个人理解,Java反射和Java反序列漏洞息息相关,很多反序列化payload的构造(比如ysoserial里的)都是基于反射的。

比如项目里加载了某些jar包的类,可以利用反射来构造并调用这些类的方法,比如上面弹出计算器的例子。

文章来源:https://blog.csdn.net/qq_46081990/article/details/135082561
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。