目录
希望和各位大佬一起学习,如果文章内容有错请多多指正,谢谢!?
个人博客链接:CH4SER的个人BLOG – Welcome To Ch4ser's Blog
1、什么是 Java 反射
参考:JAVA安全基础(二)-- 反射机制 - 先知社区 (aliyun.com)
Java 反射是一种强大的机制,它可以在运行时动态地获取和操作类的信息。通过反射,我们可以实现一些动态的功能,并且可以更灵活地使用和扩展已有的类。片面的来讲,对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。
?
因此,Java 的反射机制与我们之前了解的 Java 运行体系没有太大区别。唯一的区别是在我们生成 .class 文件的同时,也会创建一个 Class 对象。Class 对象是所有类的类,而所有的类本身则是 Class 对象的实例。因此,反射机制并不复杂,它的核心就是获取一个类的 Class 对象,然后使用 Class 对象提供的方法来获取成员变量、成员方法和构造方法等信息,进而动态地获取一个类的属性、变量、构造方法等,并进行操作。简而言之,反射机制就是通过获取 Class 对象来实现动态获取和操作类的信息。
2、为什么要用到反射
能够在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象的具体细节。
划重点:在运行时而不是编译时。(不改变原有代码逻辑,运行的时候动态创建和编译即可)
这里补充一下 Java 的编译机制:
3、反射在安全的应用场景
首先创建一个 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");
?
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): 获取值
?
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对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值(如果没有就不写)
?
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,表示取消访问检查
?
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包的类,可以利用反射来构造并调用这些类的方法,比如上面弹出计算器的例子。