Java序列化和反序列化
字数 2121 2025-08-29 08:31:53
Java序列化与反序列化安全漏洞深度解析
一、序列化与反序列化基础概念
1.1 基本定义
- 序列化(Serialization): 将对象转换为字节序列的过程
- 反序列化(Deserialization): 把字节序列恢复为对象的过程
1.2 Java中的API实现
- ObjectOutputStream: 对象输出流,
writeObject(Object obj)方法可对指定对象进行序列化 - ObjectInputStream: 对象输入流,
readObject()方法从输入流读取字节序列并反序列化为对象
1.3 序列化数据特征
- 数据开头为"AC ED 00 05"(十六进制)
- 包含包名、类名、变量名称、类型及变量值
ObjectStreamConstants类定义:STREAM_MAGIC: 0xacedSTREAM_VERSION: 5(JDK 1.5-1.8均为此值)
二、反序列化漏洞原理
2.1 漏洞本质
当Java应用对不可信数据直接进行反序列化处理时,攻击者可构造恶意输入,在反序列化过程中产生非预期对象,可能导致任意代码执行。
2.2 关键组件:Apache Commons Collections
- 扩展了Java标准库的Collection结构
- 提供了强大的数据结构类型和集合工具类
- 广泛应用于各种Java应用开发
2.3 漏洞根源
Commons Collections中对集合操作存在可进行反射调用的方法,且反序列化时未进行校验。
三、关键类分析
3.1 Transformer接口
将对象转换为另一个对象的接口实现类:
-
InvokerTransformer
- 通过反射创建新对象实例
- 关键方法参数可控:方法名、参数类型、参数值
-
ChainedTransformer
- 将多个Transformer连接成链
- 对对象依次通过链中每个Transformer进行转换
-
ConstantTransformer
- 将对象转化为常量并返回
3.4 POC构造原理
- 构建
innerMap键值对并赋值 - 利用
TransformedMap.decorate()方法对Map的value进行transform - 当value执行完整转换链时完成命令执行
3.5 触发机制
- 重写
readObject()方法的类在反序列化时会被优先调用 AnnotationInvocationHandler类的memberValues是Map类型- 其
readObject()中对memberValues的每一项调用setValue()
四、WebLogic相关漏洞
4.1 漏洞列表
- CVE-2015-4852
- CVE-2016-0638
- CVE-2016-3510
- CVE-2017-3248
4.2 T3协议特点
- Weblogic使用T3协议传输序列化数据
- 数据包分为6部分,前4字节为总长度
- 必须先发送T3协议头再发送序列化数据才能触发漏洞
4.3 各漏洞特点
CVE-2015-4852
- 黑名单过滤:
org.apache.commons.collections.functors* com.sun.org.apache.xalan.internal.xsltc.trax* javassist* org.codehaus.groovy.runtime.ConvertedClosure org.codehaus.groovy.runtime.ConversionHandler org.codehaus.groovy.runtime.MethodClosure - 反序列化点:
- weblogic.rjvm.InboundMsgAbbrev.class::ServerChannelInputStream
- weblogic.rjvm.MsgAbbrevInputStream.class
- weblogic.iiop.Utils.class
CVE-2016-0638
- 将反序列化对象封装进
weblogic.corba.utils.MarshalledObject - 不在黑名单中,可正常反序列化
- 反序列化时再次反序列化封装对象,绕过黑名单
CVE-2017-3248
- 利用黑名单外的反序列化类
- 通过JRMP协议(Java远程消息交换协议)执行任意payload
五、漏洞利用方法
5.1 利用步骤
- 找到接受外部输入的序列化对象接收点
- 确认应用Class Path包含漏洞组件(如Commons Collections)
- 使用ysoserial生成payload
- 通过对象注入方式触发反序列化
5.2 关键点
- 用恶意序列化数据替换正常数据
- 利用反射调用
Runtime.getRuntime().exec()
5.3 JRMP利用
- 使用
JRMPListener.javapayload - 序列化
RemoteObjectInvocationHandler - 使用
UnicastRef对象建立TCP连接获取RMI registry - 通过JRMP协议实现未授权远程代码执行
六、防御措施
- 升级受影响组件版本
- 实施严格的反序列化白名单机制
- 对输入数据进行严格验证
- 使用安全框架如SerialKiller
- 在反序列化前进行签名验证
七、检测与验证
7.1 检测方法
- 检查应用是否使用受影响组件
- 查找反序列化入口点
- 尝试发送测试payload观察响应
7.2 验证POC示例
# 示例检测代码框架
import socket
import time
def t3handshake(sock, server_addr):
# T3协议握手实现
pass
def buildT3RequestObject(sock, port):
# 构建T3请求对象
pass
def sendEvilObjData(sock, data):
# 发送恶意序列化对象
pass
def checkVul(res, server_addr, index):
# 检查漏洞是否存在
pass
八、总结
Java反序列化漏洞危害严重,影响范围广,攻击者可利用此漏洞实现远程代码执行。理解其原理和利用方式对安全防护至关重要,建议开发和安全人员深入掌握相关技术细节,采取有效措施防范此类风险。