Java反序列化漏洞

序列化与反序列化:

序列化的数据是方便存储的,而存储的状态信息想要再次调用就需要反序列化 

序列化就是把对象的状态信息转换为字节序列(即可以存储或传输的形式)过程

反序列化即逆过程,由字节流还原成对象

字节序是指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序。

作用: 

  1. 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
  2. 2.在网络上传送对象的字节序列。

应用场景:

在很多应用中,需要对某些对象进行序列化,让它们离开内存空间,入住物理硬盘,以便减轻内存压力或便于长期保存。

比如最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些seesion先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。

java反序列化漏洞修复方案 java反序列化漏洞利用_网络安全

 

对象序列化包括如下步骤:

1创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;

2通过对象输出流的writeObject()方法写对象。

  对象反序列化的步骤如下:

1创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;

2通过对象输入流的readObject()方法读取对象。

漏洞原因

我们既然已经知道了序列化与反序列化的过程,那么如果反序列化的时候,这些即将被反序列化的数据是我们特殊构造的呢!

如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。

漏洞触发场景

在java编写的web应用与web服务器间java通常会发送大量的序列化对象例如以下场景:

HTTP请求中的参数,cookies以及Parameters。

RMI协议,被广泛使用的RMI协议完全基于序列化

JMX 同样用于处理序列化对象

自定义协议 用来接收与发送原始的java对象

漏洞查找方式

反序列化输入点

首先应找出readObject方法调用,在找到之后进行下一步的注入操作。一般可以通过以下方法进行查找:

源码审计:寻找可以利用的“靶点”,即确定调用反序列化函数readObject的调用地点。

对该应用进行网络行为抓包,寻找序列化数据,如wireshark,tcpdump等

java序列化的数据一般会以标记(ac ed 00 05)开头,base64编码后的特征为rO0AB。

再考察应用的Class Path中是否包含Apache Commons Collections库

生成反序列化的payload,最后提交我们的payload数据

序列化常用工具

ysoserial是一个生成序列化payload数据的工具。当中针对Apache Commons Collections 3的payload也是基于TransformedMap和InvokerTransformer来构造的,然而在触发时,并没有采用上文介绍的AnnotationInvocationHandler,而是使用了java.lang.reflect.Proxy中的相关代码来实现触发。此处不再做深入分析,有兴趣的读者可以参考ysoserial的源码。

下载地址

https://github.com/frohoff/ysoserial/releaseswget

https://github.com/frohoff/ysoserial/releases/download/v0.0.2/ysoserial-0.0.2-all.jar

生成payload常用指令

java -jar ysoserial-0.0.4-all.jar CommonsCollections1 '想要执行的命令' > payload.out

漏洞分析

引发:如果Java应用对用户输入,即不可信数据做了反序列化处理,那么攻击者可以通过构造恶意输入,让反序列化产生非预期的对象,非预期的对象在产生过程中就有可能带来任意代码执行。

原因: 类ObjectInputStream在反序列化时,没有对生成的对象的输入做限制,使攻击者利用反射调用函数进行任意命令执行。

CommonsCollections组件中对于集合的操作存在可以进行反射调用的方法

根源:Apache Commons Collections允许链式的任意的类函数反射调用

问题函数:org.apache.commons.collections.Transformer接口

利用:要利用Java反序列化漏洞,需要在进行反序列化的地方传入攻击者的序列化代码。

思路:攻击者通过允许Java序列化协议的端口,把序列化的攻击代码上传到服至于如何使用这个漏洞对系统发起攻击,举一个简单的思路,通过本地java程序将一个带有后门漏洞的jsp(一般来说这个jsp里的代码会是文件上传和网页版的SHELL)序列化,

将序列化后的二进制流发送给有这个漏洞的服务器,服务器会反序列化该数据的并生成一个webshell文件,然后就可以直接访问这个生成的webshell文件进行进一步利用。