对shiro 550和721的漏洞原理学习
字数 1647 2025-08-10 13:48:19
Apache Shiro 反序列化漏洞深入分析(CVE-2016-4437 Shiro-550 & CVE-2019-12422 Shiro-721)
1. Shiro-550 漏洞分析
1.1 漏洞原理
Shiro-550(CVE-2016-4437)是一个反序列化漏洞,其核心问题在于:
- 硬编码密钥:Shiro框架使用了硬编码的AES加密密钥(
kPH+bIxk5D2deZiIxcaaaA==) - 不安全的RememberMe功能:Shiro接受Cookie中的rememberMe参数,进行以下危险操作:
- Base64解码
- AES解密(使用硬编码密钥)
- 反序列化解密后的数据
1.2 漏洞触发流程
- 攻击者构造恶意序列化对象
- 使用硬编码密钥进行AES加密
- 将加密结果进行Base64编码
- 放入Cookie的rememberMe字段发送给服务器
- 服务器端处理流程:
AbstractRememberMeManager#getRememberedPrincipals → CookieRememberMeManager#getRememberedSerializedIdentity (Base64解码) → convertBytesToPrincipals (AES解密 + 反序列化)
1.3 关键代码分析
// 硬编码密钥位置
public abstract class AbstractRememberMeManager implements RememberMeManager {
private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
// ...
}
// 漏洞触发点
public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {
byte[] bytes = getRememberedSerializedIdentity(subjectContext); // 获取并Base64解码
if (bytes != null && bytes.length > 0) {
try {
return convertBytesToPrincipals(bytes); // 解密+反序列化
} catch (Exception e) {
// ...
}
}
return null;
}
1.4 影响版本
Apache Shiro 1.x < 1.2.5
1.5 利用限制与绕过
-
反序列化限制:
- Shiro重写了
ObjectInputStream.resolveClass方法,使用ClassUtils.forName而非Class.forName - 导致非Java自身数组类无法加载(如CommonsCollections6中的Transformer数组)
- Shiro重写了
-
绕过方法:
- 方法1:使用
TemplatesImpl#newTransformer绕过// 利用链关键节点 TemplatesImpl#newTransformer → getTransletInstance → ... → Runtime.exec - 方法2:使用TrAXFilter.class + Templates.class组合
- 方法3:在没有CC组件时使用CB链
- 方法4:通过JRMP协议绕过
- 在VPS搭建JRMP服务端
- 本地搭建JRMP客户端接收返回数据
- 使用脚本进行Shiro加密处理
- 方法1:使用
1.6 POC示例
// 生成恶意payload示例
public class ShiroPOC {
public static void main(String[] args) throws Exception {
byte[] payloads = new CommonsCollections6().getPayload("calc");
AesCipherService aes = new AesCipherService();
byte[] key = java.util.Base64.getDecoder().decode("kPH+bIxk5D2deZiIxcaaaA==");
ByteSource ciphertext = aes.encrypt(payloads, key);
System.out.println(ciphertext.toString()); // 输出加密后的rememberMe值
}
}
1.7 修复方案
- Shiro 1.2.5版本修复:
- 系统启动时生成新密钥
- 允许用户手动配置cipherKey
- 注意:如果用户设置的密钥泄漏或太简单,仍可能被攻击
2. Shiro-721 漏洞分析
2.1 漏洞原理
Shiro-721(CVE-2019-12422)是一个Padding Oracle攻击漏洞:
- 加密模式问题:RememberMe默认使用AES-128-CBC模式加密
- Padding Oracle漏洞:攻击者可以通过观察服务器的响应差异,逐步解密或加密任意数据
2.2 影响版本
Apache Shiro < 1.4.2
2.3 利用条件
- 获取一个有效的rememberMe值(合法用户的登录凭证)
- 服务器对Padding错误有可区分的响应
2.4 攻击步骤
- 获取合法rememberMe Cookie
- 使用Padding Oracle攻击工具:
java -jar PaddingOracleAttack-1.0-SNAPSHOT.jar http://target.com - 构造恶意反序列化payload
- 通过Padding Oracle攻击加密payload
- 替换rememberMe值发送给服务器
2.5 修复方案
- 升级到Shiro 1.4.2及以上版本
- 使用更安全的加密模式(如AES-GCM)
3. 防御建议
- 及时升级:使用Shiro最新版本
- 密钥管理:
- 不要使用默认密钥
- 定期轮换密钥
- 使用强随机生成的密钥
- 禁用RememberMe:如非必要,禁用此功能
- 输入过滤:对Cookie值进行严格校验
- 反序列化防护:
- 使用白名单控制可反序列化的类
- 使用安全的ObjectInputStream实现
4. 工具推荐
- Shiro-550利用工具:
- ysoserial
- shiro-exploit
- Shiro-721利用工具:
- PaddingOracleAttack
- longofo师傅的项目
5. 总结
Shiro反序列化漏洞展示了框架安全设计的常见问题:
- 硬编码凭证
- 不安全的默认配置
- 危险的功能实现
理解这些漏洞原理不仅有助于防御,也能提升安全开发意识。在实际开发中,应当遵循最小权限原则和安全默认值原则,避免类似漏洞的出现。