Apacha-Shiro PaddingOracle 分析
字数 1411 2025-08-26 22:11:45
Apache Shiro Padding Oracle漏洞分析与利用教学文档
一、漏洞背景
Apache Shiro是一个功能强大且易用的Java安全框架,提供认证、授权、加密和会话管理等功能。在Shiro的RememberMe功能实现中存在Padding Oracle漏洞(CVE-2019-12422,SHIRO-721),允许攻击者在特定条件下通过Padding Oracle攻击获取加密密钥,进而实现反序列化RCE。
二、环境搭建
- 获取漏洞版本代码:
git clone https://github.com/apache/shiro.git shiro-root
cd shiro-root
git checkout -f shiro-root-1.4.0
- 搭建环境可参考SHIRO-550的搭建方式
三、漏洞分析
1. SHIRO-550回顾
- 触发点:cookie中的RememberMe字段
- 漏洞触发流程:
- Base64解码
- 使用AES解密
- 反序列化解密后的字符串
- Shiro 1.2.5之前:AES密钥硬编码在源码中,可直接构造反序列化payload实现RCE
- Shiro 1.2.5之后:采用随机密钥,需要新的攻击方式
2. SHIRO-721漏洞原理
通过Padding Oracle攻击获取AES密钥:
-
Padding验证机制:
- 当修改padding值时:
- padding正确但反序列化错误 → 抛出"deserialize error"
- padding错误 → 抛出"padding error"
- 当修改padding值时:
-
关键代码分析:
-
padding正确但反序列化错误的处理:
try { ObjectInputStream ois = new ClassResolvingObjectInputStream(bis); @SuppressWarnings({"unchecked"}) T deserialized = (T) ois.readObject(); ois.close(); return deserialized; } catch (Exception e) { String msg = "Unable to deserialize argument byte array."; throw new SerializationException(msg, e); } -
padding错误的处理:
try { return cipher.doFinal(bytes); } catch (Exception e) { String msg = "Unable to execute 'doFinal' with cipher instance [" + cipher + "]."; throw new CryptoException(msg, e); }
-
-
关键问题:
- Shiro对所有解密错误统一处理为调用
removeFrom,最终返回deleteMe - 这使得无法直接构造Padding Oracle所需的bool条件
- Shiro对所有解密错误统一处理为调用
-
解决方案:
- 利用Java反序列化的特性:
ObjectOutputStream以队列方式读取数据,后面拼接无关内容不会影响反序列化 - 在抓取的rememberMe值后附加新的IV和value,既能成功反序列化,又能验证padding正确性
- 利用Java反序列化的特性:
3. 权限验证机制
Shiro接口验证有两种权限:
authc:需要认证通过user:需要登录过(包括通过rememberMe登录)
如果开启了rememberMe功能:
user权限可以通过authc权限无法通过
四、利用条件
- 可以登录系统(获取初始有效cookie)
- 找到使用rememberMe的接口(具有
user权限的接口) - 可以进行Padding Oracle攻击
五、本地测试
- 使用公开的PoC工具(如ysoserial)
- 测试URLDNS验证漏洞存在性
六、实战挖掘案例
以RuoYi CMS(使用Shiro 1.4.1)为例:
- 登录接口分析:
public AjaxResult ajaxLogin(String username, String password, Boolean rememberMe) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password, rememberMe);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
return success();
} ...
}
- 权限配置分析:
// 所有请求需要认证
filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
- 确认所有接口都有
user权限,满足利用条件
七、防御措施
- 升级到Shiro 1.4.2及以上版本
- 禁用rememberMe功能(如不需要)
- 使用自定义密钥而非随机密钥
- 实施严格的输入验证和过滤
八、参考资源
- Shiro Padding Oracle Attack分析
- 官方漏洞公告和补丁说明
附录:技术要点总结
- Padding Oracle攻击:利用服务器对不同padding状态的响应差异获取加密信息
- CBC模式特性:了解CBC模式的加密过程和IV的作用
- Java反序列化特性:理解ObjectOutputStream的队列式读取特性
- Shiro权限模型:清楚区分authc和user权限的区别