【java安全】从0到1--第3章
2023-5-23 22:24:59 Author: 安全圈小王子(查看原文) 阅读量:15 收藏

点击蓝字
关注我们

微信搜一搜
暗魂攻防实验室

知识点

1、JavaEE-反射机制-开发和安全应用场景

2、JavaEE-反射机制-类&成员变量&方法&构造方法操作

3、JavaEE-反射机制-安全应用&反射执行&反序列化链相关

项目案例

Java-反射-Class对象类获取

Java-反射-Field成员变量类获取

Java-反射-Method成员方法类获取

Java-反射-Constructor构造方法类获取、

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

Java-反射

1、什么是Java反射

参考:https://xz.aliyun.com/t/9117

Java提供了一套反射API,该API由Class类与java.lang.reflect类库组成。

该类库包含了Field、Method、Constructor等类。

对成员变量,成员方法和构造方法的信息进行的编程操作可以理解为反射机制。

2、为什么要用到反射

参考:https://xz.aliyun.com/t/9117

其实从官方定义中就能找到其存在的价值,在运行时获得程序或程序集中每一个类型的成员和成员的信息,从而动态的创建、修改、调用、获取其属性,而不需要事先知道运行的对象是谁。划重点:在运行时而不是编译时。(不改变原有代码逻辑,自行运行的时候动态创建和编译即可)

3、反射机制应用

开发应用场景:

Spring框架的IOC基于反射创建对象和设置依赖属性。

SpringMVC的请求调用对应方法,也是通过反射。

JDBC的Class#forName(String className)方法,也是使用反射。

安全应用场景:

构造利用链,触发命令执行

反序列化中的利用链构造

动态获取或执行任意类中的属性或方法

动态代理的底层原理是反射技术

rmi反序列化也涉及到反射操作

新建项目ReflectDemo

public(公共属性) private(私有属性)protected(保护属性)

建立一个User类

package com.example.reflectdemo;
public class User {
//成员变量 public String name = "ZhangSan"; public int age = 31; private String gender = "man"; protected String job = "sec";
//构造方法 public User(){ System.out.println("调用了User()方法,但方法无参数"); } public User(String name){ System.out.println(name); }
//成员方法 private User(String name,int age){ System.out.println(name); System.out.println(age); }

protected void Users(String name,int age){ System.out.println(name); System.out.println(age); }}

建立一个GetClass类,来进行获取(用4种方法来获取类)

package com.example.reflectdemo;
public class GetClass { public static void main(String[] args) throws ClassNotFoundException {
//1.根据全限定类名:Class.forName("全路径类名") Class aClass = Class.forName("com.example.reflectdemo.User"); System.out.println("1.根据全限定类名:"+aClass);
//2.根据类名:类名.class Class userclass = User.class; System.out.println("2.根据类名:"+userclass);
//3.根据对象:对象.getClass() User user = new User(); Class aClass1 = user.getClass(); System.out.println("3.根据对象:"+aClass1);
//4、通过类加载器获得Class对象: // ClassLoader.getSystemClassLoader().loadClass("全路径类名");
ClassLoader clsload = ClassLoader.getSystemClassLoader(); Class aClass2 = clsload.loadClass("com.example.reflectdemo.User"); System.out.println("4.通过类加载器获得Class对象:"+aClass1); }}

建立GetField类

使用Field[] getFields()拿到公共成员变量

package com.example.reflectdemo;import java.lang.reflect.Field;
public class GetField { public static void main(String[] args) throws ClassNotFoundException { //Field[] getFields()获取所有公共成员变量对象的数组 Class aClass = Class.forName("com.example.reflectdemo.User"); Field[] fields = aClass.getFields();
for (Field fd:fields){ System.out.println(fd); }
}}

使用Field[] getDeclaredFields()返回所有成员变量对象的数组

package com.example.reflectdemo;

import java.lang.reflect.Field;
public class GetField { public static void main(String[] args) throws ClassNotFoundException { Class aClass = Class.forName("com.example.reflectdemo.User"); /*//Field[] getFields()获取所有公共成员变量对象的数组 Field[] fields = aClass.getFields(); for (Field fd:fields){ System.out.println(fd); }*/
//Field[] getDeclaredFields()获取所有成员变量对象的数组 Field[] fields = aClass.getDeclaredFields(); for (Field fd:fields){ System.out.println(fd); } }}

Field getField()获取单个公共成员变量

Field getDeclaredField()获取单个私有成员变量

package com.example.reflectdemo;

import java.lang.reflect.Field;
public class GetField { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class aClass = Class.forName("com.example.reflectdemo.User"); /*//Field[] getFields()获取所有公共成员变量对象的数组 Field[] fields = aClass.getFields(); for (Field fd:fields){ System.out.println(fd); System.out.println(fd); }*/
/*//Field[] getDeclaredFields()获取所有成员变量对象的数组 Field[] fields = aClass.getDeclaredFields(); for (Field fd:fields){ System.out.println(fd); }*/

//Field getField()获取单个公共成员变量 Field name = aClass.getField("name"); System.out.println("获取单个公共成员变量:"+name);
//Field getDeclaredField()获取单个私有成员变量 Field gender = aClass.getDeclaredField("gender"); System.out.println("获取单个私有成员变量:"+gender); }}

以上都是获取对象,关键是下边的赋值以及获取值!!!

利用反射获取成员变量

Object get(Object obj)获取age值

package com.example.reflectdemo;

import java.lang.reflect.Field;
public class GetField { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Class aClass = Class.forName("com.example.reflectdemo.User"); /*//Field[] getFields()获取所有公共成员变量对象的数组 Field[] fields = aClass.getFields(); for (Field fd:fields){ System.out.println(fd); System.out.println(fd); }*/
/*//Field[] getDeclaredFields()获取所有成员变量对象的数组 Field[] fields = aClass.getDeclaredFields(); for (Field fd:fields){ System.out.println(fd); }*/

/*//Field getField()获取单个公共成员变量 Field name = aClass.getField("name"); System.out.println("获取单个公共成员变量:"+name);
//Field getDeclaredField()获取单个私有成员变量 Field gender = aClass.getDeclaredField("gender"); System.out.println("获取单个私有成员变量:"+gender); */

//拿到user的类 User u = new User(); Field field = aClass.getField("age"); System.out.println(field);
//Object get(Object obj)获取公共变量age值 Object a = field.get(u); System.out.println(a); }}

field.set(Object obj,Object value)修改公共变量age值

package com.example.reflectdemo;

import java.lang.reflect.Field;
public class GetField { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException { Class aClass = Class.forName("com.example.reflectdemo.User"); /*//Field[] getFields()获取所有公共成员变量对象的数组 Field[] fields = aClass.getFields(); for (Field fd:fields){ System.out.println(fd); System.out.println(fd); }*/
/*//Field[] getDeclaredFields()获取所有成员变量对象的数组 Field[] fields = aClass.getDeclaredFields(); for (Field fd:fields){ System.out.println(fd); }*/

/*//Field getField()获取单个公共成员变量 Field name = aClass.getField("name"); System.out.println("获取单个公共成员变量:"+name);
//Field getDeclaredField()获取单个私有成员变量 Field gender = aClass.getDeclaredField("gender"); System.out.println("获取单个私有成员变量:"+gender); */

//拿到user的类 User u = new User(); Field field = aClass.getField("age"); System.out.println(field);
//Object get(Object obj)获取公共变量age值 Object a = field.get(u); System.out.println(a);
//field.set(Object obj,Object value)修改公共变量age值 field.set(u,33); Object aa = field.get(u); System.out.println(aa);

}}

拿到类,然后对类下的某个参数进行操作。

利用反射获取构造方法

新建GetConstructor

获取类里的公共的构造方法

package com.example.reflectdemo;import java.lang.reflect.Constructor;
public class GetConstructor { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//1.获取类 Class aClass = Class.forName("com.example.reflectdemo.User");
//2.获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); }
}

}

获取类里的所有的构造方法

package com.example.reflectdemo;import java.lang.reflect.Constructor;
public class GetConstructor { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取类 Class aClass = Class.forName("com.example.reflectdemo.User");
/* //获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } */
//获取类里的所有的构造方法 Constructor[] constructors1 = aClass.getDeclaredConstructors(); for (Constructor con:constructors1){ System.out.println(con); } }

}

获取类里单个公共构造方法对象

package com.example.reflectdemo;
import java.lang.reflect.Constructor;
public class GetConstructor { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取类 Class aClass = Class.forName("com.example.reflectdemo.User");
/* //获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } */
/* //获取类里的所有的构造方法 Constructor[] constructors1 = aClass.getDeclaredConstructors(); for (Constructor con:constructors1){ System.out.println(con); } */
//获取类里单个公共构造方法对象 Constructor constructor = aClass.getConstructor(String.class); System.out.println(constructor);
}}

获取类里单个构造方法

package com.example.reflectdemo;import java.lang.reflect.Constructor;
public class GetConstructor { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
//获取类 Class aClass = Class.forName("com.example.reflectdemo.User");
/* //获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } */
/* //获取类里的所有的构造方法 Constructor[] constructors1 = aClass.getDeclaredConstructors(); for (Constructor con:constructors1){ System.out.println(con); } */
/*//获取类里单个公共构造方法 Constructor constructor = aClass.getConstructor(String.class); System.out.println(constructor); */
//获取类里单个构造方法 Constructor constructor1 = aClass.getDeclaredConstructor(String.class,int.class); System.out.println(constructor1); }}

利用反射调用构造方法吗,并修改方法

package com.example.reflectdemo;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.reflectdemo.User");
/* //获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } */
/* //获取类里的所有的构造方法 Constructor[] constructors1 = aClass.getDeclaredConstructors(); for (Constructor con:constructors1){ System.out.println(con); } */
/*//获取类里单个公共构造方法 Constructor constructor = aClass.getConstructor(String.class); System.out.println(constructor); */
/*//获取类里单个构造方法 Constructor constructor1 = aClass.getDeclaredConstructor(String.class,int.class); System.out.println(constructor1); */
//对构造方法进行操作 Constructor con2 = aClass.getDeclaredConstructor(String.class, int.class);
//临时开启对私有的访问 con2.setAccessible(true); User uu=(User) con2.newInstance("Lisi",999); System.out.println(uu); }
}

对构造方法进行操作(1个参数string)

package com.example.reflectdemo;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.reflectdemo.User");
/* //获取类里的公共的构造方法 Constructor[] constructors = aClass.getConstructors(); for (Constructor constructor:constructors){ System.out.println(constructor); } */
/* //获取类里的所有的构造方法 Constructor[] constructors1 = aClass.getDeclaredConstructors(); for (Constructor con:constructors1){ System.out.println(con); } */
/*//获取类里单个公共构造方法 Constructor constructor = aClass.getConstructor(String.class); System.out.println(constructor); */
/*//获取类里单个构造方法 Constructor constructor1 = aClass.getDeclaredConstructor(String.class,int.class); System.out.println(constructor1); */
/*//对构造方法进行操作 Constructor con2 = aClass.getDeclaredConstructor(String.class, int.class);
//临时开启对私有的访问 con2.setAccessible(true); User uu=(User) con2.newInstance("Lisi",999); System.out.println(uu); */
//对构造方法进行操作(1个参数string) Constructor con3 = aClass.getConstructor(String.class); con3.newInstance("TestAAA");

}

}

利用反射获取成员方法

新建GetMethod类

Method[] GetMethds()获取包括继承的公共成员方法

package com.example.reflectdemo;import java.lang.reflect.Method;
public class GetMethod { public static void main(String[] args) throws ClassNotFoundException { Class aClass = Class.forName("com.example.reflectdemo.User"); //Method[] GetMethds()获取包括继承的公共成员方法 Method[] methods = aClass.getMethods(); for (Method me:methods){ System.out.println(me); }
}
}

这个不是很理解...不过问题不大,学就完了!!

Method[] GetDeclaredMethods()获取不包括继承的所有成员方法

package com.example.reflectdemo;import java.lang.reflect.Method;
public class GetMethod { public static void main(String[] args) throws ClassNotFoundException { Class aClass = Class.forName("com.example.reflectdemo.User");
/*//Method[] GetMethds()获取包括继承的公共成员方法 Method[] methods = aClass.getMethods(); for (Method me:methods){ System.out.println(me); }*/
//Method[] GetDeclaredMethods()获取不包括继承的所有成员方法 Method[] methods = aClass.getDeclaredMethods(); for (Method me:methods){
System.out.println(me);
} }
}

Method[] GetMethod()获取单个成员方法

package com.example.reflectdemo;import java.lang.reflect.Method;
public class GetMethod { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException { Class aClass = Class.forName("com.example.reflectdemo.User");
/*//Method[] GetMethds()获取包括继承的公共成员方法 Method[] methods = aClass.getMethods(); for (Method me:methods){ System.out.println(me); }*/
/*//Method[] GetDeclaredMethods()获取不包括继承的所有成员方法 Method[] methods = aClass.getDeclaredMethods(); for (Method me:methods){
System.out.println(me);
} */

//Method[] GetMethod()获取单个成员方法 Method users = aClass.getDeclaredMethod("Users", String.class, int.class); System.out.println(users); }
}

Method类创建对象方法,并进行执行

package com.example.reflectdemo;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.reflectdemo.User");
/*//Method[] GetMethds()获取包括继承的公共成员方法 Method[] methods = aClass.getMethods(); for (Method me:methods){ System.out.println(me); }*/
/*//Method[] GetDeclaredMethods()获取不包括继承的所有成员方法 Method[] methods = aClass.getDeclaredMethods(); for (Method me:methods){
System.out.println(me);
} */

/*//Method[] GetMethod()获取单个成员方法 Method users = aClass.getDeclaredMethod("Users", String.class, int.class); System.out.println(users); */
//Method类创建对象方法 User u =new User(); Method users = aClass.getDeclaredMethod("Users", String.class, int.class); users.invoke(u,"wangwu",60); }}

java调用链

package com.example.reflectdemo;import java.io.IOException;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自带的Runtime.java //<1.8>->rt.jar->java->lang->Runtime //Runtime.getRuntime().exec("calc");
//三方jar包,假设现在引用了三方jar包 Class aClass = Class.forName("java.lang.Runtime");
/* //拿到三方jar的方法 Method[] methods = aClass.getMethods();
//遍历输出jar类,发现找到getRuntime() for (Method me:methods){ System.out.println(me); }
*//* "C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:F:\java-test\IntelliJ IDEA 2023.1.1\lib\idea_rt.jar=59480:F:\java-test\IntelliJ IDEA 2023.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;F:\java-test\ReflectDemo\target\classes" com.example.reflectdemo.GetRunExec public void java.lang.Runtime.exit(int) public void java.lang.Runtime.runFinalization() public static void java.lang.Runtime.runFinalizersOnExit(boolean) public void java.lang.Runtime.load(java.lang.String) public void java.lang.Runtime.loadLibrary(java.lang.String) public native void java.lang.Runtime.gc() public static java.lang.Runtime java.lang.Runtime.getRuntime() public native long java.lang.Runtime.freeMemory() public native long java.lang.Runtime.maxMemory() public void java.lang.Runtime.addShutdownHook(java.lang.Thread) public native int java.lang.Runtime.availableProcessors() public java.lang.Process java.lang.Runtime.exec(java.lang.String,java.lang.String[]) throws java.io.IOException public java.lang.Process java.lang.Runtime.exec(java.lang.String) throws java.io.IOException public java.lang.Process java.lang.Runtime.exec(java.lang.String[]) throws java.io.IOException public java.lang.Process java.lang.Runtime.exec(java.lang.String[],java.lang.String[],java.io.File) throws java.io.IOException public java.lang.Process java.lang.Runtime.exec(java.lang.String[],java.lang.String[]) throws java.io.IOException public java.lang.Process java.lang.Runtime.exec(java.lang.String,java.lang.String[],java.io.File) throws java.io.IOException public java.io.InputStream java.lang.Runtime.getLocalizedInputStream(java.io.InputStream) public java.io.OutputStream java.lang.Runtime.getLocalizedOutputStream(java.io.OutputStream) public void java.lang.Runtime.halt(int) public boolean java.lang.Runtime.removeShutdownHook(java.lang.Thread) public native long java.lang.Runtime.totalMemory() public native void java.lang.Runtime.traceInstructions(boolean) public native void java.lang.Runtime.traceMethodCalls(boolean) public final void java.lang.Object.wait() throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public java.lang.String java.lang.Object.toString() public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll()
public static java.lang.Runtime java.lang.Runtime.getRuntime() *//* */
//获取getRuntime成员方法 Method getRuntime = aClass.getMethod("getRuntime");
//获取exec成员方法,这边是从上边的遍历类里面找出来的 //public java.lang.Process java.lang.Runtime.exec(java.lang.String[]) throws java.io.IOException Method exec = aClass.getMethod("exec", String.class);
//使用getRuntime方法去执行 Object runtime = getRuntime.invoke(aClass); exec.invoke(runtime,"calc.exe");
}}

危害

不安全的反射对象指应用程序使用具有反射功能的外部输入来选择要使用的类或代码,可能被攻击者利用而输入或选择不正确的类。绕过身份验证或访问控制检查参考分析:https://zhuanlan.zhihu.com/p/165273855利用结合:https://xz.aliyun.com/t/7031(反序列化利用链)

后续反序列化相关工具

ysoserial.jar//github搜索

java安全从0到1-第1章

【java安全】从0到1--第2章

网络安全新赛道-数据安全生命周期

anhunsec_redteam_V2.4 正式版红队渗透系统简介

微信搜一搜
暗魂攻防实验室

文章来源: http://mp.weixin.qq.com/s?__biz=Mzg4MjY3NDI5Mw==&mid=2247486452&idx=2&sn=da5cfae21577dd62ddd0b14d31821ef4&chksm=cf5254eef825ddf8ab055a76b0ea3dfbf5a5f535f2e0605c3f88322e25f7c9a43c3eb985583c#rd
如有侵权请联系:admin#unsafe.sh