Apache Shiro源码浅析之从远古洞到最新PaddingOracle CBC
字数 1357 2025-08-25 22:59:03

Apache Shiro安全框架深度解析:从远古反序列化漏洞到Padding Oracle CBC攻击

0x00 前言

Apache Shiro是一个功能强大且易于使用的Java安全框架,提供以下核心功能模块:

  • Authentication:身份认证
  • Authorization:授权验证
  • Session Manager:会话管理
  • Cryptography:加密
  • Web Support:Web支持
  • Caching:缓存
  • Concurrency:多线程
  • Testing:测试模块
  • Run As:用户伪装
  • Remember Me:记住我功能

0x01 Shiro源码深度解析

1. Shiro基础配置与使用

1.1 依赖配置(pom.xml)

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.2.4</version>
</dependency>
<!-- 其他相关依赖 -->

1.2 Web配置(web.xml)

<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

1.3 Shiro核心配置(spring-shiro.xml)

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/login.jsp"/>
    <property name="filterChainDefinitions">
        <value>
            /admin/**=authc,roles[admin]
            /user/**=user,roles[user]
        </value>
    </property>
</bean>

2. Shiro核心运行机制

2.1 过滤器链初始化流程

  1. DelegatingFilterProxy代理ShiroFilterFactoryBean
  2. ShiroFilterFactoryBean创建AbstractShiroFilter实例
  3. 初始化默认过滤器(11个):
    • anon:匿名访问
    • authc:需要认证
    • logout:注销
    • perms:权限验证
    • roles:角色验证
    • user:RememberMe功能

2.2 请求处理流程

  1. 请求到达AbstractShiroFilter.doFilterInternal()
  2. 创建Subject对象:
    Subject subject = createSubject(request, response);
    
  3. 执行过滤器链:
    executeChain(request, response, chain);
    

2.3 RememberMe机制实现

关键类:CookieRememberMeManager

  • 从Cookie读取rememberMe值
  • Base64解码
  • AES解密
  • 反序列化为PrincipalCollection对象

0x02 反序列化远古漏洞(Shiro <= 1.2.4)

漏洞成因

  1. AbstractRememberMeManager使用固定AES密钥:
    private static final byte[] DEFAULT_CIPHER_KEY_BYTES = 
        Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
    
  2. 攻击者可构造恶意序列化数据,加密后作为rememberMe Cookie发送
  3. 服务端解密后反序列化导致RCE

漏洞利用

利用ysoserial生成payload并加密:

byte[] payload = generatePayload("CommonsCollections6", "calc");
byte[] encrypted = encryptWithAES(payload, DEFAULT_KEY);
String rememberMe = Base64.encode(encrypted);

修复方案

Shiro 1.2.5+改为启动时随机生成密钥:

setCipherKey(cipherService.generateNewKey().getEncoded());

0x03 Padding Oracle CBC攻击(Shiro <= 1.4.1)

攻击原理

  1. Shiro对解密失败的响应特征:
    • Padding错误:返回rememberMe=deleteMe Cookie
    • Padding正确:正常响应
  2. 利用特征进行Padding Oracle攻击

攻击条件

  1. 需要至少一个配置了user过滤器的端点
  2. 服务端对padding错误有明确响应

攻击步骤

  1. 构造恶意序列化数据
  2. 分段进行CBC翻转攻击
  3. 通过响应判断padding是否正确
  4. 最终构造出有效的攻击payload

Java实现示例

public void attack(byte[] payload) {
    byte[] originCookie = Base64.decode(rememberMe);
    
    CBCResult result = PaddingOracleCBCForShiro.paddingOracleCBC(payload, data -> {
        byte[] newCookie = combineArrays(originCookie, data);
        return sendRequest(newCookie);
    });
    
    System.out.println("Exploit Cookie: " + Base64.encode(result.getFullCookie()));
}

参考资源

  1. Padding Oracle攻击分析
  2. Shiro Padding Oracle Attack
  3. Java序列化分析
  4. marshalsec工具

防御建议

  1. 及时升级到最新版本
  2. 自定义RememberMe加密密钥
  3. 限制反序列化类白名单
  4. 监控异常rememberMe请求
Apache Shiro安全框架深度解析:从远古反序列化漏洞到Padding Oracle CBC攻击 0x00 前言 Apache Shiro是一个功能强大且易于使用的Java安全框架,提供以下核心功能模块: Authentication:身份认证 Authorization:授权验证 Session Manager:会话管理 Cryptography:加密 Web Support:Web支持 Caching:缓存 Concurrency:多线程 Testing:测试模块 Run As:用户伪装 Remember Me:记住我功能 0x01 Shiro源码深度解析 1. Shiro基础配置与使用 1.1 依赖配置(pom.xml) 1.2 Web配置(web.xml) 1.3 Shiro核心配置(spring-shiro.xml) 2. Shiro核心运行机制 2.1 过滤器链初始化流程 DelegatingFilterProxy 代理 ShiroFilterFactoryBean ShiroFilterFactoryBean 创建 AbstractShiroFilter 实例 初始化默认过滤器(11个): anon:匿名访问 authc:需要认证 logout:注销 perms:权限验证 roles:角色验证 user:RememberMe功能 2.2 请求处理流程 请求到达 AbstractShiroFilter.doFilterInternal() 创建Subject对象: 执行过滤器链: 2.3 RememberMe机制实现 关键类: CookieRememberMeManager 从Cookie读取rememberMe值 Base64解码 AES解密 反序列化为PrincipalCollection对象 0x02 反序列化远古漏洞(Shiro <= 1.2.4) 漏洞成因 AbstractRememberMeManager 使用固定AES密钥: 攻击者可构造恶意序列化数据,加密后作为rememberMe Cookie发送 服务端解密后反序列化导致RCE 漏洞利用 利用ysoserial生成payload并加密: 修复方案 Shiro 1.2.5+改为启动时随机生成密钥: 0x03 Padding Oracle CBC攻击(Shiro <= 1.4.1) 攻击原理 Shiro对解密失败的响应特征: Padding错误:返回 rememberMe=deleteMe Cookie Padding正确:正常响应 利用特征进行Padding Oracle攻击 攻击条件 需要至少一个配置了 user 过滤器的端点 服务端对padding错误有明确响应 攻击步骤 构造恶意序列化数据 分段进行CBC翻转攻击 通过响应判断padding是否正确 最终构造出有效的攻击payload Java实现示例 参考资源 Padding Oracle攻击分析 Shiro Padding Oracle Attack Java序列化分析 marshalsec工具 防御建议 及时升级到最新版本 自定义RememberMe加密密钥 限制反序列化类白名单 监控异常rememberMe请求