安全学习_开发相关_Java反射机制基础及对安全测试影响


参考文章:

反射基础参考:https://xz.aliyun.com/t/9117

不安全的反射对象参考分析:https://zhuanlan.zhihu.com/p/165273855

不安全的反射对象利用结合:https://xz.aliyun.com/t/7031(反序列化利用链)

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反序列化也涉及到反射操作

Java-反射-获取类的Class对象

获取到类的Class对象之后可以对类的成员Field、Constructor、Method进行获取修改等操作。

1、由类名获取:类名.class

// 获取User类的Class对象
Class userClass = User.class;

2、由对象获取:对象.getClass()

User user = new User();
// 由user对象获取User类的Class对象
Class aClass = user.getClass();

3、由全限定类名获取:Class.forName(“全路径类名”)

Class aClass1 = Class.forName("com.reflectdemo.User");

4、通过类加载器获得Class对象:

//ClassLoader.getSystemClassLoader().loadClass("全路径类名");
// 通过ClassLoader类加载器和全路径类名获取类的Class对象
ClassLoader clsload=ClassLoader.getSystemClassLoader();
Class aClass = clsload.loadClass("com.reflectdemo.User");

Java-反射-操作Field成员变量

获取类的Field成员变量

类的Field成员变量需要由类的Class对象获取

Class aClass = Class.forName("com.reflectdemo.User");

//获取公共成员变量对象
    Field[] fields=aClass.getFields();

//获取所有成员变量对象
    Field[] fields=aClass.getDeclaredFields();

//更具成员变量名获取公共,私有单个成员变量对象
    Field field=aClass.getField("name");
    Field field=aClass.getDeclaredField("age");

Field成员变量获取值和赋值

//成员变量值获取和赋值

    User user = new User();

    Field field=aClass.getField("age");
// 为成员变量field(User中的age)赋值,赋值对象是user
    field.set(user,30);
// 获取user中成员变量field(age)的值。
    Object a=field.get(user);

    System.out.println(a);

Java-反射-操作Method成员方法

获取类的Method成员方法

Class aClass = Class.forName("com.reflectdemo.User");

//以数组的形式返回所有公共成员方法对象Method,包含继承的方法,包含Object中的方法。
    Method[] methods = aClass.getMethods();

//返回所有成员方法对象的数组,不包括继承的
    Method[] methods = aClass.getDeclaredMethods();

//根据方法名和参数返回单个公共成员方法的Method对象
    Method methods = aClass.getMethod("getName");
    Method methods = aClass.getMethod("setName", String.class);//参数要传对应class

//返回单个成员方法对象
    Method methods = aClass.getDeclaredMethod("UserInfo", String.class, int.class, String.class);

运行成员方法invoke

	Class aClass = Class.forName("com.reflectdemo.User");    
// 获取方法单个方法userInfo
	Method methods = aClass.getDeclaredMethod("userInfo", String.class, int.class, String.class);
	
    User u = new User();

// 私有方法需要开启临时权限才能够执行
    methods.setAccessible(true);
// 执行方法,对应第一个参数:执行方法的对象,第二个参数之后:方法参数。
    methods.invoke(u,"user",18,"man");

Java-反射-操作Constructor构造方法

获取构造方法对象Constructor

	Class aClass = Class.forName("com.reflectdemo.User");

//以数组的形式返回所有public构造方法对象Constructor(不包括private
    Constructor[] constructors = aClass.getConstructors();


//以数组的形式返回所有构造方法对象Constructor(包括private
    Constructor[] constructors = aClass.getDeclaredConstructors();




 //根据参数,返回单个公共构造方法对象Constructor
    Constructor con1=aClass.getConstructor(); // 返回无参的构造方法
    Constructor con2=aClass.getConstructor(String.class); // 返回有一个String类型参数的构造方法




//根据参数返回单个构造方法对象Constructor
    Constructor con3=aClass.getDeclaredConstructor(int.class);
    Constructor con4=aClass.getDeclaredConstructor(String.class,int.class, String.class);

通过获取的Constructor构造方法对象Constructor创建对象

//获取Constructor对象
    Constructor con2=aClass.getDeclaredConstructor(int.class);
// 若Constructor为私有属性,则需要临时将其设置为公开。
    con2.setAccessible(true);
// 通过该Constructor创建对象
    User uu=(User) con2.newInstance("chuan",18);

Java-反射-实现不安全命令执行

Java实现-命令执行

  • 原型:
Runtime.getRuntime().exec("calc");
  • 反射:
// 获取Runtime类的class对象
Class aClass = Class.forName("java.lang.Runtime");

// 获取该类的exec(String)方法
Method exec = aClass.getMethod("exec", String.class);
// 获取该类的getRuntime()方法
Method getRuntimeMethod = aClass.getMethod("getRuntime");
// 执行getRuntimeMethod()方法以获取Runtime类的对象
Object runtime = getRuntimeMethod.invoke(aClass);
// 用runtime对象执行exec(String)方法
exec.invoke(runtime, "calc.exe");



Class c1= Class.forName("java.lang.Runtime");
// 获取类的无参构造器(私有)
Constructor m = c1.getDeclaredConstructor();
// 临时将私有属性设为可访问
m.setAccessible(true);
// 使用构造器m创建实例并执行命令运行。
c1.getMethod("exec", String.class).invoke(m.newInstance(), "calc");

不安全的反射对象

指应用程序使用具有反射功能的外部输入来选择要使用的类或代码,

可能被攻击者利用而输入或选择不正确的类。绕过身份验证或访问控制检查

参考分析:https://zhuanlan.zhihu.com/p/165273855

利用结合:https://xz.aliyun.com/t/7031(反序列化利用链)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值