Shiro rememberMe 反序列化漏洞复现(550 与 721)

区分 Shiro-550(硬编码默认密钥)与 Shiro-721(Padding Oracle),完整讲解两者的原理、影响、利用、检测、防御与修复。

写在前面:合法学习边界

本文复现只在本机靶场进行。Shiro 反序列化利用可直接控制目标机器,禁止对非授权目标使用。

一、先分清两个漏洞

Shiro 的 rememberMe 反序列化问题常被笼统叫“Shiro 反序列化”,但实战中要严格区分两个编号,利用方式完全不同:

1
2
Shiro-550(CVE-2016-4437):密钥泄露型
Shiro-721:Padding Oracle 型(不依赖密钥)
1
2
550:rememberMe 用硬编码默认密钥 AES 加密 → 知道密钥就能构造
721:密钥是随机的 → 用 CBC Padding Oracle 逐字节改密文,不猜密钥

识别第一步永远先看密钥:能解出默认密钥就按 550 打;解不出再考虑 721。

二、Shiro-550:硬编码密钥反序列化

原理

1
2
3
4
1. rememberMe Cookie = AES(序列化对象)
2. 默认密钥 kPH+bIxk5D2deZiIxcaaaA== 是公开的
3. 攻击者用同一把密钥加密恶意序列化对象
4. 服务端反序列化执行 → RCE

常见默认密钥:

1
2
kPH+bIxk5D2deZiIxcaaaA==
4AvVhmFLUs0KTA3Kprsdag==

影响版本:Shiro <= 1.2.4,以及使用弱/默认密钥的版本。

影响

1
2
3
远程代码执行(RCE)
服务器被直接控制
内网横向

风险等级:严重。

利用

1
2
3
1. ysoserial 生成 gadget(CommonsCollections6 "id")
2. 用默认 AES 密钥加密
3. Base64 后放进 rememberMe Cookie

常用工具:ShiroExploit / Shiro_attack-2.2,内置默认密钥字典一键打。

检测与修复

1
2
检测:抓 rememberMe Cookie,用默认密钥字典解密
修复:升级 Shiro 1.4.2+,自定义高强度密钥,密钥不进代码库

三、Shiro-721:Padding Oracle 利用

原理

721 的密钥是随机生成的,但 rememberMe 用的是 AES-CBC 模式。CBC 的解密过程里,前一组的密文(或 IV)被拿来 XOR 后一组明文,攻击者可以通过不断修改密文、观察服务端是否报错(PaddingError/deleteMe 差异),逐字节恢复明文或构造合法密文。

1
利用的是“加密算法模式”的弱点,而不是密钥

影响版本:Shiro < 1.4.2(CBC 模式,且报错信息可区分)。

影响

1
2
同 550:远程代码执行
但需要大量请求(打一次可能几万次试错)

风险等级:高到严重(条件更苛刻)。

利用要点

1
2
3
1. 需要一个合法可解密的 rememberMe(先登录拿一个)
2. 基于 Padding Oracle 修改密文 → 最终恢复 AES 密钥或直接构造恶意明文
3. 用恢复出的密钥/构造结果打反序列化

工具:shiro_721_exp、部分 ShiroExploit 版本支持。

为什么难

1
2
耗时高、请求量大、容易触发 WAF 告警
不同版本对 PaddingError 的回显差异不同

检测与修复

1
2
检测:大量 deleteMe/异常长 rememberMe 请求、高频试错流量
修复:升级 Shiro 1.4.2+(改用 GCM 等认证加密模式),并升级反序列化防护

四、统一防御与修复

1
2
3
4
5
6
升级 Shiro 到 1.4.2+,关闭 CBC 弱模式
自定义高强度密钥并定期轮换
反序列化加类白名单
WAF 拦截异常长的 rememberMe
监控批量探测行为
修复后复测:550 默认密钥解不出、721 试错被阻断

五、小结

遇到 Shiro,先分 550 还是 721:先试默认密钥(550),解不出再考虑 Padding Oracle(721)。两者编号不同、原理不同、利用成本不同,混为一谈会在实战里浪费时间。

本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
最后更新于 Aug 29, 2026 14:00 +0800