(1):概述

序列化是把对象转换成字节流,便于保存在内存,文件,数据库中;

反序列化既是相反的过程,由字节流还原成对象;Java中的ObjectOutputStream类的writeObject()方法用于序列化,类ObjectInputStream类的readObject()方法用于反序列化:

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

问题的根源在于类ObjectOutInputStream在反序列化时,没有对生产的对象的类型做限制,假如反序列化可以设置Java类型的白名单,那么问题的影响就会小了很多。

(2):出现场合

由于Java序列化与反序列化是让 Java 对象脱离 Java
运行环境的一种手段,可以有效的实现多平台之间的通信、对象持久化存储,所以以下多种场合都会存在于该漏洞;

比如HTTP(多平台之间的通信管理等)RMI(Java中一组拥护开发分布式应用程序的API,实现了不同操作系统程序的方法调用,需要注意的是RMI 的传输 100%
基于反序列化,Java RMI 的默认端口是 1099 端口)
JMX(JMX 是一套标准的代理和服务,用户可以在任何 Java 应用程序中使用这些代理和服务实现管理,中间件软件 WebLogic
的管理页面就是基于 JMX 开发的,而 JBoss 则整个系统都基于 JMX 构架)

此外WebLogic(用纯java开发的用来构建网站的必要软件,具有解析、发布网页等功能JBOSS(一款免费,开放源代码J2EE的实现,通过LGPL许可证进行发布,需要的内存和硬盘空间比较小,且安装简单,一般与Tomcat或Jetty绑定使用的应用服务器),这两款中间件的部分版本也有该漏洞,还有WebSphere,Jenkins 和OpenNMS等,其中Jenkins收到该漏洞影响较大Weblogic因为公开到公网的数据较少,所以受影响面也稍微少一些,而Jboss因为需要/invoker/JMXInvokerServlet的支持,受影响面稍小;此外凡是使用了commons-collections.jar包的都会收到影响,以及在其他语言中,例如PHP和Python中也有相似的问题;

(3):漏洞利用概述

首先拿到一个Java应用,找到一个接受外部输入的序列化对象的接收点,即反序列化漏洞的触发点。一般可以通过审计源码中对反序列化函数的调用(例如readObject())来寻找,也可以直接通过对应用交互流量进行抓包,查看流量中是否包含java序列化数据来判断,java序列化数据的特征为以标记(aced 00 05)开头,确定了反序列化输入点后,再查看应用的Class Path中是否包含Apache Commons

Collections库(ysoserial所支持的其他库亦可),如果是,就可以使用ysoserial来生成反序列化的payload,指定库名和想要执行的命令即可,然后通过先前找到的传入对象方式进行对象注入,数据中载入payload,触发受影响应用中ObjectInputStream的反序列化操作,随后通过反射调用Runtime.getRunTime.exec即可完成利用;

(4):漏洞防范措施以及检测

避免传递敏感数据,在对象中,可以使用关键字transient修饰敏感数据的变量,这样它就不会写入到序列化流中;
传递敏感数据时,可以对数据进行先签名后加密,这样别人也就不会很轻易的解密以及伪造;

由于反序列化操作一般在导入模版文件、网络通信、数据传输、日志格式化存储、对象数据落磁盘或DB存储等业务场景,所以在代码审计时可重点关注一些反序列化操作函数并判断输入是否可控,比如:ObjectInputStream.readObject,ObjectInputStream.readUnshared,XMLDecoder.readObject,Yaml.load,Xstream.fromXml,ObjectMapper.readValue,JSON.praseObject等;

可以着重注意传入数据的校验,服务器权限和相关日志的检查, API权限控制,通过 HTTPS加密传输数据等方面;

由于很多提供反序列化操作的公共接口,所以使用第三方库反序列化接口就不好用白名单的方式来修复了,这个时候作为第三方库也不知道谁会调用接口,会反序列化什么类。所以这个时候可以使用黑名单的方式来禁止一些已知危险的类被反序列化,具体的黑名单类可参考contrast-rO0、ysoserial中paylaod包含的类;

可以使用白盒检测,或者是自动化静态代码审计工具去检测;

可以使用黑盒检测,比如:调用ysoserial并依次生成各个第三方库的利用payload(也可以先分析依赖第三方包量,调用最多几个库的paylaod即可),该payload构造为访问特定url链接的payload,根据http访问请求记录判断反序列化漏洞是否利用成功; 

使用RASP检测反序列化漏洞,通过重写ObjectInputStream对象的resolveClass方法获取反序列化的类即可实现对反序列化类的黑名单校验(由于Java程序中类ObjectInputStream的readObject方法被用来将数据流反序列化为对象,如果流中的对象是class,则它的ObjectStreamClass描述符会被读取,并返回相应的class对象,ObjectStreamClass包含了类的名称及serialVersionUID。类的名称及serialVersionUID的ObjectStreamClass描述符在序列化对象流的前面位置,且在readObject反序列化时首先会调用resolveClass读取反序列化的类名,所以可以使用RASP检测反列化漏洞)

攻击检测(通过查看反序列化后的数据,可以看到反序列化数据开头包含两字节的魔术数字,这两个字节始终为十六进制的0xAC
ED,接下来是两字节的版本号,考虑到zip、base64各种编码,在攻击检测时可针对该特征进行匹配请求post中是否包含反序列化数据,判断是否为反序列化漏洞攻击)

(5):总结

在实战中的Java站点越来越多,所以Java反序列化漏洞的利用也越来越显得重要。除了常见的Web服务反序列化,安卓、桌面应用、中间件、工控组件等等的反序列化,以及XML(前一阵的Weblogic挖矿事件就是XMLDecoder引起的Java反序列化)、JSON、RMI等细致化的分类;

所以代码审计及渗透测试就变得重要点,具体可以参考Java反序列化漏洞备忘单(该内容为其他前辈整理与收集),里面集合了目前关于Java反序列化研究的大会PPT、PDF文档、测试代码,以及权威组织发布的漏洞研究报告,还有被反序列化攻破的应用清单(附带POC)。

有关漏洞方面的问题其实也是一个庞大的知识体系,所以多跟同行业以及前辈交流学习是提供技术水平的最好方法。

源链接

Hacking more

...