看了很多大佬们的博客,发现java的反序列化漏洞都绕不开反射,大多数payload也与反射机制密切相关,由此先从反射机制做下总结
java反射机制
在此之前,我们先要了解Class类以及其方法
Class类详细讲解
这里列出相关重要的方法
根据类名获取类 forname()
获取类下的函数 get Method()
执行类下的函数 invoke()
这个方法位于getMethod()里面,传的参数需要传一个实例化的类
实例化类的对象 newInstance()
将类进行实例化,在forName获得类对象后,使用该方法将其实例化,这个方法好像不能调用有参构造方法
同样上述的invoke也可以用newInstance()来进行实例化
补充说明,如果要获取的方法要传参的话,需要传入该参数的类型以及值
如下:
以上为四个方法的讲解
尝试弹出计算器
先说说RunTime类
这个类是专门运行命令的,用法如下
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("calc.exe");
接着尝试用Class类调用
Class.forName("java.lang.Runtime").getMethod("exec", String.class).invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime").invoke(Class.forName("java.lang.Runtime")),"calc.exe");
一句话调用计算机
为什么这么长呢,因为在调用exec方法之前需要调用getRuntime()方法,这也说明了exec是一个私有方法
可能会有人说了这玩意这么麻烦,何必呢?
接下来就是这个类的厉害之处,他能够直接调用私有方法
调用私有方法
getDeclaredMethod、getDeclaredConstructor和getMethod、getConstructor使用方法是一致的
其中getDeclaredConstructor调用私有方法
通过Constructor 类来进行调用
还是以弹计算机为例
Class cls = Class.forName("java.lang.Runtime");
Constructor m = cls.getDeclaredConstructor();
m.setAccessible(true);
cls.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
通过getDeclaredConstructor()方法设置私有方法可访问,即可成功调用
调用指定构造方法
指定的构造方法生成类的实例
上面这篇文章讲的特别清楚,我也是看这篇文章学的
- getConsturctor()函数可以选定指定接口格式的构造函数
- getMethod 方法获取的是当前类中所有公共方法,包括从父类继承的方法
- getDeclared 方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私有的方法,但从父类里继承来的就不包含了
下面来试试如何调用有参构造方法和无参构造方法,无参构造方法其实在newInstance()的时候也会自动调用,但这里还是多说下
我们可以发现第一个成功调用有参构造方法,并且成功调用私有变量,而第二个只调用了无参构造方法,并没有调用有参构造方法.
反射调用有参方法
这个也可以通过上述分析那四个方法调用,也可用Method类进行调用
参考(鸣谢):
https://xz.aliyun.com/t/7029
https://blog.csdn.net/sun1318578251/article/details/105814323