java反序列化漏洞及其检测

【摘要】1java反序列化简介java反序列化是近些年安全业界研究的重点领域之一 , 在ApacheCommonsCollections、JBoss、WebLogic等常见容器、库中均发现有该类漏洞 , 而且该类型漏洞容易利用 , 造成的破坏很大 , 因此影响广泛 。 在本文中将先介绍java反序列化漏洞的原理 , 然后在此基础上介绍安全工具如何检测、扫描此类漏洞 。 1.1什么是反序列化Java序列化是指...
java反序列化是近些年安全业界研究的重点领域之一 , 在ApacheCommonsCollections、JBoss、WebLogic等常见容器、库中均发现有该类漏洞 , 而且该类型漏洞容易利用 , 造成的破坏很大 , 因此影响广泛 。
在本文中将先介绍java反序列化漏洞的原理 , 然后在此基础上介绍安全工具如何检测、扫描此类漏洞 。
Java序列化是指把Java对象转换为字节序列的过程 , 序列化后的字节数据可以保存在文件、数据库中;而Java反序列化是指把字节序列恢复为Java对象的过程 。 如下图所示:
java反序列化漏洞及其检测
文章图片
序列化和反序列化通过ObjectInputStream.readObject()和ObjectOutputStream.writeObject()方法实现 。
在java中任何类如果想要序列化必须实现java.io.Serializable接口 , 例如:publicclassHelloimplementsjava.io.Serializable{Stringname;}
java.io.Serializable其实是一个空接口 , 在java中该接口的唯一作用是对一个类做一个标记让jre确定这个类是可以序列化的 。
同时java中支持在类中定义如下函数:privatevoidwriteObject(java.io.ObjectOutputStreamout)throwsIOExceptionprivatevoidreadObject(java.io.ObjectInputStreamin)throwsIOException,ClassNotFoundException;
这两个函数不是java.io.Serializable的接口函数 , 而是约定的函数 , 如果一个类实现了这两个函数 , 那么在序列化和反序列化的时候ObjectInputStream.readObject()和ObjectOutputStream.writeObject()会主动调用这两个函数 。 这也是反序列化产生的根本原因
例如:publicclassHelloimplementsjava.io.Serializable{Stringname;privatevoidreadObject(java.io.ObjectInputStreamin)throwsIOException,ClassNotFoundException{Runtime.getRuntime().exec(name);}}
该类在反序列化的时候会执行命令 , 我们构造一个序列化的对象 , name为恶意命令 , 那么在反序列化的时候就会执行恶意命令 。
在反序列化的过程中 , 攻击者仅能够控制“数据” , 无法控制如何执行 , 因此必须借助被攻击应用中的具体场景来实现攻击目的 , 例如上例中存在一个执行命令的可以序列化的类(Hello) , 利用该类的readObject函数中的命令执行场景来实现攻击
在这里我们构造一个有漏洞的靶场进行漏洞复现测试:使用spring-boot编写一个可以接收http数据并反序列化的应用程序 。
使用https://start.spring.io/生成一个spring-boot应用 , 选择MavenProject、java8
java反序列化漏洞及其检测
文章图片
下载到本地 , 导入IDE , 修改pom.xml加入ApacheCommonsCollections3.1依赖(该版本存在反序列化漏洞)commons-collectionscommons-collections3.1
修改DemoApplication.java为如下代码packagecom.example.demo;importjava.io.IOException;importjava.io.ObjectInputStream;importjavax.servlet.http.HttpServletRequest;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.bind.annotation.GetMapping;@SpringBootApplication@RestControllerpublicclassDemoApplication{publicstaticvoidmain(String[]args){SpringApplication.run(DemoApplication.class,args);}@GetMapping("/hello")publicStringhello(){return"helloworld";}//反序列化接口@PostMapping("/rmi")publicStringrmi(HttpServletRequestrequest){try{ObjectInputStreamois=newObjectInputStream(request.getInputStream());Objectobj=(Object)ois.readObject();return"unmarshal"+obj.getClass().getName()+"ok";}catch(ClassNotFoundException|IOExceptione){return"unmarshalfailed";}}}