Day34:安全开发-JavaEE应用&反射机制&攻击链&类对象&成员变量方法&构造方法
一,Java-反射
1,反射的含义:
反射的意思就是,在代码运行的时候,还能动态的获得和修改成员变量,操作成员方法和构造方法。而不是得将程序停掉,再来改源代码里面的东西。对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。
2,反射的意义:
在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可)
3,安全应用场景:
(1)构造利用链,触发命令执行
(2)反序列化中的利用链构造
4,Java-反射-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(); ClassLoader clsload=ClassLoader.getSystemClassLoader(); Class aClass2=clsload.loadClass("com.example.reflectdemo.User")
反射实验:创建一个User类,包含成员变量和成员方法,构造方法,便于获取反射所对应需要
User.java文件
package com.example; public class User { //成员变量 public String name="xiaodi"; public int age = 31; private String gender="man"; protected String job="sec"; //构造方法 public User(){ //System.out.println("无参数"); } public User(String name){ System.out.println("我的名字"+name); } private User(String name,int age){ System.out.println(name); System.out.println(age); } //成员方法 public void userinfo(String name,int age,String gender,String job){ this.job=job; this.age=age; this.name = name; this.gender=gender; } protected void users(String name,String gender){ this.name = name; this.gender=gender; System.out.println("users成员方法:"+name); System.out.println("users成员方法:"+gender); } }
GetClass.java文件
package com.example; public class GetClass { public static void main(String[] args) throws ClassNotFoundException { //1、根据全限定类名:Class.forName("全路径类名") Class aClass = Class.forName("com.example.User"); System.out.println(aClass); //2、根据类名:类名.class Class userClass = User.class; System.out.println(userClass); //3、根据对象:对象.getClass() User user= new User(); Class aClass1 = user.getClass(); System.out.println(aClass1); //4、通过类加载器获得Class对象://ClassLoader.getSystemClassLoader().loadClass("全路径类名"); ClassLoader clsload=ClassLoader.getSystemClassLoader(); Class aClass2 = clsload.loadClass("com.example.User"); System.out.println(aClass2); } }
5,Java-反射-Field成员变量类获取
//Class aClass = Class.forName("com.example.reflectdemo.User"); //获取公共成员变量对象 // Field[] fields=aClass.getFields(); // for(Field f:fields){ // System.out.println(f); // } //获取所有成员变量对象 // Field[] fields=aClass.getDeclaredFields(); // for(Field f:fields){ // System.out.println(f); // } //获取公共,私有单个成员变量对象 // Field field=aClass.getField("age"); // Field field=aClass.getDeclaredField("gender"); // System.out.println(field); //城边变量值获取和赋值 // User u = new User(); // Field field=aClass.getField("age"); // field.set(u,30); // Object a=field.get(u); // System.out.println(a);
GetField.java
package com.example; import java.lang.reflect.Field; public class GetField { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Class aClass = Class.forName("com.example.User"); //获取公共的成员变量 // Field[] fields = aClass.getFields(); // for(Field fd:fields){ // System.out.println(fd); // } //获取所有的成员变量 // Field[] fields = aClass.getDeclaredFields(); // for(Field fd:fields){ // System.out.println(fd); // } //获取单个的公共成员变量 Field name = aClass.getField("name"); System.out.println(name); //获取单个的成员变量 Field gender = aClass.getDeclaredField("gender"); System.out.println(gender); //获取公共的成员变量age的值 User u = new User(); Field field=aClass.getField("age"); //取值 Object a=field.get(u); System.out.println(a); //赋值 field.set(u,32); Object aa=field.get(u); System.out.println(aa); } }
二,Java-反射-Constructor构造方法类获取
//Class aClass = Class.forName("com.example.reflectdemo.User"); //返回所有公共构造方法对象的数组 // Constructor[] constructors = aClass.getConstructors(); // for(Constructor con:constructors){ // System.out.println(con); // } //返回所有构造方法对象的数组 // Constructor[] constructors = aClass.getDeclaredConstructors(); // for(Constructor con:constructors){ // System.out.println(con); // } //返回单个公共构造方法对象 // Constructor con1=aClass.getConstructor(); // Constructor con1=aClass.getConstructor(String.class); // System.out.println(con1); //返回单个构造方法对象 // Constructor con2=aClass.getDeclaredConstructor(int.class); //Constructor con2=aClass.getDeclaredConstructor(String.class,int.class, String.class); // System.out.println(con2); // Constructor con2=aClass.getDeclaredConstructor(int.class); // con2.setAccessible(true); // User uu=(User) con2.newInstance("xiaodi",30,"man"); // System.out.println(uu);
GetConstructor.java
package com.example; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class GetConstructor { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { Class aClass = Class.forName("com.example.User"); //获取公共的构造方法 // Constructor[] constructors = aClass.getConstructors(); // for (Constructor con:constructors){ // System.out.println(con); // } //获取所有的构造方法 // Constructor[] constructors = aClass.getDeclaredConstructors(); // for (Constructor con:constructors){ // System.out.println(con); // } //获取单个的公共的构造方法 // Constructor constructor = aClass.getConstructor(String.class); // System.out.println(constructor); // // //获取单个的构造方法 // Constructor con1 = aClass.getDeclaredConstructor(String.class,int.class); // System.out.println(con1); //对构造方法进行操作(两个参数string,int) // Constructor con2=aClass.getDeclaredConstructor(String.class,int.class); // //临时开启对私有的访问 // con2.setAccessible(true); // User uu=(User) con2.newInstance("xiaodigaygay",40); // System.out.println(uu); //对构造方法进行执行(1个参数strin) Constructor con2=aClass.getConstructor(String.class); con2.newInstance("xiaodigaygay"); } }
三,Java-反射-Method成员方法类获取
//Class aClass = Class.forName("com.example.reflectdemo.User"); //返回所有公共成员方法对象的数组,包括继承的 // Method[] methods = aClass.getMethods(); // for (Method me:methods){ // System.out.println(me); // } //返回所有成员方法对象的数组,不包括继承的 // Method[] methods = aClass.getDeclaredMethods(); // for (Method me:methods){ // System.out.println(me); // } //返回单个公共成员方法对象 // Method methods = aClass.getMethod("getName"); // System.out.println(methods); // Method methods = aClass.getMethod("setName", String.class); // System.out.println(methods); //返回单个成员方法对象 // Method methods = aClass.getDeclaredMethod("UserInfo", String.class, int.class, String.class); // System.out.println(methods); //运行方法invoke // Method methods = aClass.getDeclaredMethod("UserInfo", String.class, int.class, String.class); // User u = new User(); // //私有需要开启临时 // methods.setAccessible(true); // methods.invoke(u,"xiaodi",18,"man");
GetMethod.java
package com.example; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class GetMethod { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { Class aClass = Class.forName("com.example.User"); //获取包括继承的公共成员方法 // Method[] methods = aClass.getMethods(); // for(Method me:methods){ // System.out.println(me); // } //获取不包括继承的所有成员方法 // Method[] methods = aClass.getDeclaredMethods(); // for(Method me:methods){ // System.out.println(me); // } //获取单个的成员方法 // Method users = aClass.getDeclaredMethod("users", String.class,String.class); // System.out.println(users); // 对成员方法进行执行 // invoke() 方法用于调用指定对象的方法,并传递相应的参数。 User u = new User(); Method users = aClass.getDeclaredMethod("users", String.class,String.class); users.invoke(u,"xiaodigay","gay1"); } }
四,Java-反射-不安全命令执行&反序列化链构造
1 、反射实现 - 命令执行 -原型: Runtime.getRuntime().exec("calc"); -反射: Class aClass = Class.forName("java.lang.Runtime"); Method[] methods = aClass.getMethods(); for (Method me:methods){ System.out.println(me); } Method exec = aClass.getMethod("exec", String.class); Method getRuntimeMethod = aClass.getMethod("getRuntime"); Object runtime = getRuntimeMethod.invoke(aClass); exec.invoke(runtime, "calc.exe"); Class c1= Class.forName("java.lang.Runtime"); Constructor m = c1.getDeclaredConstructor(); m.setAccessible(true); c1.getMethod("exec", String.class).invoke(m.newInstance(), "calc"); 2、不安全的反射对象 指应用程序使用具有反射功能的外部输入来选择要使用的类或代码, 可能被攻击者利用而输入或选择不正确的类。绕过身份验证或访问控制检查 参考分析:https://zhuanlan.zhihu.com/p/165273855 利用结合:https://xz.aliyun.com/t/7031(反序列化利用链)
GetRunExec.java
package com.example; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class GetRunExec { public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { //原生调用 JDK自带的rt.jar // Runtime.getRuntime().exec("calc"); //如果是第三方的jar包 //通过 Class.forName("java.lang.Runtime") 方法获取了 java.lang.Runtime 类的 Class 对象,并将其赋值给 aClass。 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"); } }
文章参考https://blog.csdn.net/qq_61553520/article/details/136611937?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522baec5cd87d3bc16a3b87a813b077294a%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=baec5cd87d3bc16a3b87a813b077294a&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-136611937-null-null.nonecase&utm_term=34&spm=1018.2226.3001.4450
本文作者:破防剑客
本文链接:https://www.cnblogs.com/sec-geek/p/18612073
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步