java反序列化学习

Posted by bfpiaoran on December 6, 2018

java虽然看了语法 但是好多都没看过  最近总被问到序列化与反序列化漏洞的问题 很尴尬 特找个时间看了下实现

java序列化是为了实现减少内存开销,将一部分暂时不需要的通过序列化成文件流的形势存储到硬盘上,以减小内存的压力,之后需要用到的时候再通过反序列化读取到内存之中

java本着一切皆为对象的原则,理论上什么都可以序列化的,但是序列化需要implements   java.io.Serializable的接口

Serializable无任何意义  只用于标识可序列化的语义 也就是说只有实现Serializable接口的对象才可以被序列化

 

 

package test;


import java.io.*;


public class Objectest {
	public static final File FILE = new File("test.ser");  
	public static void main(String[] args) throws Exception {
		ser(new Person("test",20));
		dser();
	    
	}
	public static void ser(Object obj) throws FileNotFoundException, IOException{  //序列化
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE));
		oos.writeObject(obj);
		oos.close();
		
	}
	public static void dser() throws FileNotFoundException, IOException, ClassNotFoundException {  //反序列化
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE));
		System.out.println(ois.readObject());
		ois.close();
	}

}
class Person implements Serializable{
	private String name;
	private int age;
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}

 

 

那么反序列化漏洞就能大概知道 是在数据流反序列化成对象的时候产生的漏洞,而造成的代码执行

接下来看反射机制

反就是正的反义词 反射即通过对象来查找类名称

 

 

那么获取类有三种方法

一种是通过类名称.class获取

一种是通过getClass()方法获取

最后是 Class.forName()

上面例子即为

		Class<?> cls = new Person().getClass();
		Class<?> cls2 = Person.class;
		Class<?> cls3 = Class.forName("test.Person");
  		System.out.println(cls);
		System.out.println(cls2);
		System.out.println(cls3);
		

然后可以通过Instance()实例化对象

java执行命令是通过Runtime.getruntime().exec()来执行命令的

 

那么怎么通过反射机制调用类的方法呢

这里需要用的 getMethod()的invoke方法来反射调用对应的对象

那么可以这么写

 Class.forName("java.lang.Runtime")
	              .getMethod("exec", String.class)
	              .invoke(Class.forName("java.lang.Runtime").getMethod("getRuntime",new Class[]{}).invoke(null),"calc.exe");

卧槽这么烂的写法以后要看不懂了

 

简单写。。。。

	      Class<?>  clrun = Class.forName("java.lang.Runtime");
	      Method runt = clrun.getMethod("getRuntime",new Class[]{});
	      Object runa = runt.invoke(null);
	      Method execu = clrun.getMethod("exec", String.class);
	      execu.invoke(runa, "calc.exe");

 

 

呼   核心搞完了

接下来找个公开的问题练下手