在现有很多的应用当中,需要对某些对象进行序列化,让它们离开内存空间,入驻物理硬盘,以便可以长期保存,那么java序列化漏洞搭建怎么弄?今天我们就来讲解一下。
Java序列化是Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
漏洞基本原理
简单的反序列化Demo
首先定义对象类Persion,包含两个参数
public class implements java.io.Serializable { public String name; public int age; public void info() { System.out.println("Name:" + this.name + ";nAge:" + this.age); } }
在主类中声明对象,并且将对象序列化为二进制文件,将其存储到硬盘中
import java.io.*; public class Main { public static void main(String[] args) {
将对象序列化为二进制文件
Persion p = new Persion(); p.name = "Joner"; p.age = 18; try { //打开一个文件输入流 FileOutputStream fileOut = new FileOutputStream("D:\test\test.db"); //建立对象输入流 ObjectOutputStream out = new ObjectOutputStream(fileOut); //输出反序列化对象 out.writeObject(p); out.close(); fileOut.close(); System.out.printf("保存成功"); } catch (IOException i) { i.printStackTrace(); } }
进行反序列化
import java.io.*; public class Main { public static void main(String[] args) { /*从二进制文件中提取对象*/ Persion persion = null; try { FileInputStream fileInputStream = new FileInputStream("D:\test\test.db"); //建立对象输入流 ObjectInputStream inputStream = new ObjectInputStream(fileInputStream); persion = (Persion) inputStream.readObject(); inputStream.close(); fileInputStream.close(); } catch (ClassNotFoundException c) { System.out.println("对象未找到"); c.printStackTrace(); return; } catch (FileNotFoundException e) { e.printStackTrace(); return; } catch (IOException e) { e.printStackTrace(); return; } System.out.println("反序列化对象......."); System.out.println("Name:" + persion.name); System.out.println("Age:" + persion.age); } }
查看test.db文件的内容可以看见如下内容
其中 AC ED 00 05 是java 序列化内容的特征,其中00 05 是版本信息,base64编码后为ro0AB
反序列化漏洞Demo
在上面的Demo中可以看到,进行反序列化时会调用readObject()方法,如果readObject方法书写不当就会引发漏洞。
import java.io.*; public class Main { public static void main(String[] args) throws Exception { Unsafeclass unsafeclass = new Unsafeclass(); unsafeclass.name = "hhhhh"; FileOutputStream fileOutputStream = new FileOutputStream("object"); ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); //将对象写入object文件 objectOutputStream.writeObject(unsafeclass); objectOutputStream.close(); //从文件中反序列化对象 FileInputStream fileInputStream = new FileInputStream("object"); ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream); //恢复对象 Unsafeclass objectFormDisk = (Unsafeclass) objectInputStream.readObject(); System.out.println(objectFormDisk.name); objectOutputStream.close(); } } class Unsafeclass implements Serializable { public String name; //重写readObject()方法 private void readObject(java.io.ObjectInputStream inputStream) throws IOException, ClassNotFoundException { //执行默认的readObdect()方法 inputStream.defaultReadObject(); //执行打开计算器命令 Runtime.getRuntime() .exec("calc.exe"); } }
程序运行过程为:
UnsafeClass类背序列化进入object文件;
从object文件中恢复对象;
调用被恢复对象的readObject()方法;
命令被执行;
这样看感觉并不会有人会这样写readobject()这个方法,而且一些成熟的框架都会有防范反序列化的方法,但仍有很大比例的反序列化漏洞,这主要是使用了不安全的库造成的。
java序列化的知识在实际工作中是一个重点,作为java人员要将这方面的知识熟悉运用,才能在实际工作中合理的解决问题!最后大家如果想要了解更多java初识知识,敬请关注奇Q工具网。
推荐阅读: