Java反序列化
Posted Amev
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java反序列化相关的知识,希望对你有一定的参考价值。
序列化
序列化是把对象转换为字节流,以便于保存在内存、文件、数据库中。反序列化则是相反的过程,将字节流还原为对象,Java中的ObjectOutputStream类的writeObject()方法用于序列化,类ObjectInputStream类的readObject()方法用于反序列化,如果Java应用对不可信的数据进行反序列化处理,那么攻击者可以构造恶意输入,使得反序列化后产生非预期的对象,非预期的对象在产生的过程中,有可能带来任意代码执行。
出现场合:
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等,此外凡是使用了commons-collections.jar包的都会收到影响
漏洞利用:
- 找到接受外部输入的序列化对象接收点,一般可以通过审计源码中对反序列函数的调用(例如readObject()来寻找,也可以直接通过对应用交互流量进行抓包,查看流量中是否包含Java序列化数据来判断,Java序列化数据的特征以标记(aced 00 05)
- 确定了反序列化输入点后,查看应用的Class Path中是否包含Apache Commons Collections库(ysoserial所支持的其他库也行,可以使用ysoserial来生成反序列化的Payload,指定库名和想要执行的命令即可),随后生成反序列化Payload,找到传入对象方式进行对象注入,触发受影响应用中ObjectInputStream的反序列化操作,随后通过反射调用Runtime.getRunTime.exec即可完成利用.
漏洞防范:
- 在对象中使用关键字transient修饰敏感数据的变量,这样它就不会写入到序列化流中
- 传递敏感数据时,可以对数据进行先签名后加密,提高解密和伪造难度
漏洞检测:由于反序列化操作一般在导入模版文件、网络通信、数据传输、日志格式化存储、对象数据落磁盘或DB存储等业务场景,所以在代码审计时可重点关注一些反序列化操作函数并判断输入是否可控,比如:
- ObjectInputStream.readObject,
- ObjectInputStream.readunshared,
- XMLDecoder.readObject,
- Yaml.load,Xstream.fromXml,
- OjectMapper.readValue,
- JSON.praseObject等
--着重注意传入数据的校验,服务器权限和相关日志的检查,API权限控制,通过HTTPS加密传输数据等方面--
- 由于很多提供反序列化操作的公共接口,所以使用第三方库反序列化接口就不好用白名单的方式来修复了,这个时候作为第三方库也不知道谁会调用接口以及反序列化什么类。所以这个时候可以使用黑名单的方式来禁止一些已知的危险的类被反序列化,具体的黑名单类可参考contrast-rO0、ysoserial中Payload包含的类
- 白盒检测,或使用自动化静态代码审计工具
- 黑盒检测,比如:调用ysoserial并以此生成各个第三方库的利用Payload(也可以先分析依赖第三方包变量,调用最多几个库的Payload即可),该Payload构造为访问特定Url链接的Payload,根据http访问请求来记录判断反序列化漏洞是否利用成功
- 使用RASP检测反序列化漏洞,通过重写ObjectInputStream对象的resolveClass方法获取反序列化的类即可实现对反序列化的黑名单校验(由于Java程序中类ObjectInputStream的readObject方法被用来将数据流反序列化为对象,如果流中的对象是class,则它的ObjectStreamClass描述符会被读取,并返回相应的Class对象,ObjectStreamClass包含了类的名称以及serialVersionUID。类的名称及serialVersionUID的ObjectStreamClass描述符在序列化对象流的前面位置,且在readObject反序列化时,会首先调用resolveClass读取反序列化的类名,所以可以使用RASP检测反序列化漏洞)
攻击检测:通过查看反序列化后的数据,可以看到反序列化数据开头包含两字节的魔术数字,则两个字节始终为十六进制的0xACED,接下来是两字节的版本号,考虑到zip、Base64各种编码,在攻击检测时,可针对该特征进行匹配请求POST中是否包含反序列化数据,以此判断是否为反序列化漏洞攻击
除了常见的Web服务反序列化,安卓、桌面应用、中间件、工控组件等等的反序列化,以及XML、JSON、RMI等细致化的分类
以上是关于Java反序列化的主要内容,如果未能解决你的问题,请参考以下文章