前言

因为对Java Web安全这一块没有做过研究,所以趁着时间比较空闲学习一下Java Web安全的知识。

Java反射机制

什么是Java反射机制?

Java反射机制是一种间接操作目标对象的一种机制。其核心在于JVM在运行的时候再动态加载类。并且对于任意一个类,只要知道它的名称,都能知道它的所有属性和方法。对于任意一个对象,都能调用它的任意方法和属性。
Java反射机制是Java动态特性的体现,利用反射机制我们可以轻松实现对Java类的动态调用。

Java反射常用类

Java.lang.Class;

Java.lang.ClassLoader;

Java.lang.reflect.Constructor;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Modifier;

Java反射常用方法

  • forName() 获取类
  • newInstance() 初始化类
  • getMethod() 获取类的方法
  • invoke() 执行类的方法

Java反射的实现

  • Object.getClass() 如:String.getClass()
  • Test.class() 如:xxx.class()
  • Class.forName 如:class.forName(“java.lang.Runtime”)

实验 - 反射调用类方法

单例实例

Runtime类的构造方法是私有的,只能通过单例模式用静态方法获取对象,即我们只能通过Runtime().getRuntime()获取Runtime对象。

所以,对Runtime的反射代码如下:

Class class1 = Class.forName("java.lang.Runtime");   
class1.getMethod("exec",String.class).invoke(class1.getMethod("getRuntime").invoke(class1),"calc.exe");

反射的执行流程如下:

Class class1 = Class.forName("java.lang.Runtime");  
Method method1 = class1.getMethod("exec", String.class);  
Method method2 = class1.getMethod("getRuntime");  
Object run = method2.invoke(class1);  
method1.invoke(run,"calc.exe");  

这里对invoke()函数做一点解释:
invoke的功能是执行方法,第一个参数根据方法的不同而不同

  • 普通方法,则第一个参数为类的对象
  • 静态方法,则第一个参数为类

有参构造的反射

针对有参数的构造函数,需要引入一个新的反射方法getConstructor

getConstructor(),参数为目标类的构造函数参数,返回的是目标类的构造函数。

因为Runtime的构造方法是私有的,这里用ProcessBuilder来实现

Class class1 = Class.forName("java.lang.ProcessBuilder");  
class1.getMethod("start").invoke(class1.getConstructor(List.class).newInstance(Arrays.asList("calc.exe")));

用上强制转化的代码(实际环境不一定存在)

Class class1 = Class.forName("java.lang.ProcessBuilder");  
((ProcessBuilder)class1.getConstructor(List.class).newInstance(Arrays.asList("calc.exe"))).start();

私有构造函数

针对私有构造函数,我们可以通过getDeclared系列的函数进行反射。

getDeclaredMethod()可以返回目标类的所有方法,包括私有的方法。

这里用Runtime举例(因为它的构造方法是私有的)

Class class1 = Class.forName("java.lang.Runtime");  
Constructor a = class1.getDeclaredConstructor();  
a.setAccessible(true);  
class1.getMethod("exec", String.class).invoke(a.newInstance(),"calc.exe");

在这里面新出现了个setAccessible,它的作用是修改私有方法的作用域。获取私有方法后必须修改,否则无法成功调用

实验 - 反射调用类成员

调用公有变量

Class class1 = Class.forName("com.javavuln.demo.Person");
Field f1 = class1.getField("a");  
System.out.println(f1.get(class1.newInstance()));

调用所有变量

Class class1 = Class.forName("com.javavuln.demo.Person");
Field f1 = class1.getDeclaredField("b");
f1.setAccessible(true);
System.out.println(f1.get(class1.newInstance()));

参考

[https://javasec.org/javase/Reflection/Reflection.html]


Java Web安全      Java的反射机制

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

前置信息收集 下一篇