这篇文章将为大家详细讲解有关Java序列化和反序列化出现漏洞的解决方案,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
Java序列化
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
Java反序列化
反序列化就是将字节序列恢复为Java对象的过程
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象,因此可以实现多平台之间的通信、对象持久化存储,主要有如下几个应用场景。
HTTP:多平台之间的通信,管理等
RMI:是 Java 的一组拥护开发分布式应用程序的 API,实现了不同操作系统之间程序的方法调用。值得注意的是,RMI 的传输 100% 基于反序列化,Java RMI 的默认端口是1099端口。
JMX:JMX 是一套标准的代理和服务,用户可以在任何 Java 应用程序中使用这些代理和服务实现管理,中间件软件 WebLogic 的管理页面就是基于 JMX 开发的,而 JBoss 则整个系统都基于 JMX 构架。
系列化反序列化基础
序列化和反序列化本身并不存在问题。但当输入的反序列化的数据可被用户控制,那么攻击者即可通过构造恶意输入,让反序列化产生非预期的对象,在此过程中执行构造的任意代码。
一个类的对象能够序列化的成功需要两个条件
漏洞基本原理
简单的反序列化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"); } }
程序运行过程为:
这样看感觉并不会有人会这样写readobject()这个方法,而且一些成熟的框架都会有防范反序列化的方法,但仍有很大比例的反序列化漏洞,这主要是使用了不安全的库造成的。上面只是介绍了简单的Java反序列化过程,接下来会有一篇文章介绍反序列化漏洞检测方法以及复现一些经典反序列化漏洞。
关于Java序列化和反序列化出现漏洞的解决方案就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。