上次和亮去接了个渗透的比赛,结果我还是啥都不会,当时意识到现在大多数的网站的后端都基本上是 java 和 go了,想 php 的基本上比较少了,php 在以后肯定会没落的,java不想 php 那样 简单易用且灵活,所以很有必要系统性的学习一下java安全。
Java安全可以从反序列化漏洞开始说起,反序列化漏洞⼜可以从反射开始说起。 反射是⼤多数语⾔⾥都必不可少的组成部分,对象可以通过反射获取他的类,类可以通过反射拿到所有 ⽅法(包括私有),拿到的⽅法可以调⽤,总之通过“反射”,我们可以将Java这种静态语⾔附加上动态 特性。
java反射这块学校的教科书上并没有,我是参考这篇学习的 https://www.cainiaojc.com/java/java-reflection.html
Java中有一个名为Class的类,该类在运行时保留有关对象和类的所有信息。
Class对象描述了特定类的属性。该对象用于执行反射。
反射机制允许程序在执行期借助于 ReflectionAPI
取得任何类的内部信息(比如成员变量、构造器、成员方法等等),并能操作对象的属性及方法。 加载完类后,在堆中就产⽣了⼀个Class类型的对象(⼀个类只有⼀个Class对象),这个对象包含了类的完整结构 信息。通过这个对象得到类的结构。
利用反射机制可以使 java 这样的编译型语言 更加灵活起来
Java反射机制可以完成:
反射相关的主要类如下:
1、Java.lang.Class:代表⼀个类,Class对象表示某个类加载后在堆中的对象
2、Java.lang.reflect.Method:代表类的⽅法
3、Java.lang.reflect.Field:代表类的成员变量
4、Java.lang.reflect.Constructor:代表类的构造⽅法
参考 https://www.cainiaojc.com/java/java-reflection.html
使用 forName()
方法
forName()
接受字符串参数(类的名称)并返回Class对象。返回的对象引用字符串指定的类。例如,
Class Dog { }
Class c1 = Class.forName("Dog"); //获得名为Dog的Class对象
使用getClass()方法
getClass()
方法使用特定类的对象来创建新的对象Class。例如,
Dog d1 = new Dog();
Class c1 = d1.getClass();
使用.class
java 的每个类中默认会创建一个名为 class
的属性,该属性就是该类的 Class
对象
我们还可以使用 .class 扩展名创建Class对象。例如,
Class c1 = Dog.class; //使用 类名.class 获得Class对象
创建Class对象后,我们可以使用这些对象执行反射。
若一个类实现了某个接口,可以使用 Class 的 getInterfaces()
方法来获取。此方法返回一个接口数组。
Class obj = d1.getClass();//获得class对象
Class[] objInterface = obj.getInterfaces();//获得接口
类 Class 的方法 getSuperclass()
可用于获取有关特定类的父类的信息。
而且,Class提供了一种 getModifier()
方法,该方法以整数形式返回class的修饰符。
Class obj = d1.getClass();
//以整数形式获取Dog的访问修饰符
int modifier = obj.getModifiers();
//获取Dog的父类
Class superClass = obj.getSuperclass();
我们可以使用 Field
类提供的各种方法检查和修改类的不同字段。
注意:如果我们知道字段名称,则可以使用
setAccessible(true)
)例如有
class Dog {
public String type;
}
访问公共字段
Dog d1 = new Dog();
//创建Class对象
Class obj = d1.getClass();
//操纵Dog类的公共字段type
Field field1 = obj.getField("type");
//设置字段的值,第一个参数是对象实例
field1.set(d1, "labrador");
//通过转换成字符串来获取字段的值,第一个参数是对象实例
String typeValue = (String)field1.get(d1);
//获取类型的访问修饰符
int mod1 = field1.getModifiers();
String modifier1 = Modifier.toString(mod1);
访问私有字段
设有
class Dog {
private String color;
}
Dog d1 = new Dog();
//创建类Class对象
Class obj = d1.getClass();
//访问私有字段
Field field2 = obj.getDeclaredField("color");
//使私有字段可访问
field2.setAccessible(true);
//设置color值(注意第一个参数为对象实例)
field2.set(d1, "brown");
// get the value of type converting in String
String colorValue = (String)field2.get(d1);
//获取color的访问修饰符
int mod2 = field2.getModifiers();
String modifier2 = Modifier.toString(mod2);
像字段一样,我们可以使用 Method
类提供的各种方法来检查类的不同方法。
class Dog {
public void display() {
System.out.println("I am a dog.");
}
protected void eat() {
System.out.println("I eat dog food.");
}
private void makeSound() {
System.out.println("Bark Bark");
}
}
class ReflectionDemo {
public static void main(String[] args) {
try {
Dog d1 = new Dog();
//创建一个Class对象
Class obj = d1.getClass();
//使用getDeclaredMethod()获取所有方法
Method[] methods = obj.getDeclaredMethods();
//获取方法的名称
for(Method m : methods) {
System.out.println("方法名称: " + m.getName());
//获取方法的访问修饰符
int modifier = m.getModifiers();
System.out.println("修饰符: " + Modifier.toString(modifier));
//获取方法的返回类型
System.out.println("Return Types: " + m.getReturnType());
System.out.println(" ");
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Class clsd = Class.forName("Dog");
Dog dog = (Dog) clsd.newInstance();//通过反射实例化一个对象
dog.display();
//执行Dog中的display方法
public class Invo {
public static void main(String[] args) throws Exception {
execute("Dog", "display");
}
public static void execute(String className, String methodName) throws Exception {
Class clazz = Class.forName(className);
clazz.getMethod(methodName).invoke(clazz.newInstance());
}
}
class Dog {
public void display() {
System.out.println("I am a dog.");
}
}
foName
newInstance
getMethod
invoke
基本上,这几个方包揽了Java安全里各种和反射有关的Payload。
public void execute(String className, String methodName) throws Exception {
Class clazz = Class.forName(className);
clazz.getMethod(methodName).invoke(clazz.newInstance());
}