JAVA反序列化学习--shiro反序列化详解
字数 1556 2025-08-10 12:18:01
Shiro反序列化漏洞详解
一、Shiro反序列化漏洞概述
Shiro反序列化漏洞主要分为两种类型:
- Shiro-550:影响Shiro版本<1.2.5,由于AES密钥硬编码导致
- Shiro-721:影响Shiro版本≥1.2.5,由于Padding Oracle攻击导致
二、漏洞环境搭建
1. 环境准备
-
下载Shiro 1.2.4源码:
https://codeload.github.com/apache/shiro/zip/shiro-root-1.2.4 -
修改
shiro/samples/web/pom.xml:- 添加或修改jstl依赖版本为1.2
-
使用IDEA内置Tomcat服务启动
三、Shiro-550漏洞分析
1. 加密流程分析
-
登录流程入口:
AbstractShiroFilter.class第151行- 创建Subject对象
- 处理Cookie信息
-
登录成功处理:
AuthenticatingFilter.class处理登录- 登录成功后触发
onLoginSuccess
-
RememberMe处理:
DefaultSecurityManager.class的rememberMeSuccessfulLogin函数RememberMeManager不为空时继续处理
-
Cookie操作:
CookieRememberMeManager.class处理rememberMe和deleteMe字段- 通过
addCookieHeader写入Cookie
-
序列化与加密:
convertPrincipalsToBytes将身份信息序列化为字节- 使用AES/CBC/PKCS5Padding模式加密
- 密钥为硬编码的
DEFAULT_CIPHER_KEY_BYTES:kPH+bIxk5D2deZiIxcaaaA==
-
Cookie设置:
- 加密后数据Base64编码
- 加入Cookie中返回给客户端
2. 解密流程分析
-
请求处理入口:
AbstractShiroFilter.class#doFilterInternal- 创建Subject对象
- 解析身份信息
-
RememberMe处理:
RememberMeManager获取Cookie值getRememberedSerializedIdentity函数:- 获取Cookie中的值
- Base64解码生成二进制数据
-
解密与反序列化:
convertBytesToPrincipals函数:- 获取解密服务
- 解密二进制数据
- 调用
deserialize(bytes)反序列化
deserialize(bytes)中包含readObject(),触发反序列化漏洞
四、漏洞利用原理
Shiro-550利用流程
- 攻击者构造恶意序列化数据
- 使用硬编码AES密钥加密
- Base64编码后放入Cookie的rememberMe字段
- 服务端处理流程:
- 读取Cookie中rememberMe值
- Base64解码
- AES解密
- 反序列化触发漏洞
关键点
- 硬编码密钥:
kPH+bIxk5D2deZiIxcaaaA== - 加密模式:AES/CBC/PKCS5Padding
- 触发点:
readObject()反序列化
五、Shiro-721漏洞简介
Shiro 1.2.5及之后版本:
- 使用随机密钥替代硬编码密钥
- 但由于Padding Oracle攻击仍可导致反序列化漏洞
六、防御建议
- 升级到最新版本Shiro
- 禁用RememberMe功能(如不需要)
- 自定义加密密钥(替换默认密钥)
- 实施反序列化过滤器
七、总结
Shiro反序列化漏洞的核心在于:
- 身份信息的序列化/反序列化机制
- 加密密钥的管理问题(硬编码或Padding Oracle)
- 反序列化时的安全控制不足
理解这些流程对于安全研究和漏洞防护至关重要。