一种另类的shiro检测方式
字数 1650 2025-08-10 08:29:04

Apache Shiro 反序列化漏洞检测技术深度解析

0x00 前言

Apache Shiro 是一个广泛使用的 Java 安全框架,其反序列化漏洞自2016年存在,但在近年攻防演练(HVV)中备受关注。本文将深入剖析 Shiro 的检测原理,并提出一种创新的检测方法,相比传统方式具有更高准确性和可靠性。

0x01 传统检测方法分析

1.1 常规检测方式

目前业界普遍采用的 Shiro 检测方法是在请求 Cookie 中添加 rememberMe=1,然后检查响应中是否出现 rememberMe=deleteMe。这种方法的原理基于 Shiro 对 rememberMe 机制的处理流程。

1.2 传统方法的局限性

传统检测存在以下问题:

  • 依赖 DNSLOG 进行外联验证
  • 使用 Commons Collections 链进行盲测时可能存在误判
  • 无法覆盖所有可能的 gadget 利用场景

0x02 Shiro 处理机制深度分析

2.1 核心处理流程

Shiro 对 rememberMe 的处理主要在 AbstractRememberMeManager#getRememberedPrincipals 方法中:

public PrincipalCollection getRememberedPrincipals(SubjectContext subjectContext) {
    PrincipalCollection principals = null;
    try {
        byte[] bytes = this.getRememberedSerializedIdentity(subjectContext);
        if (bytes != null && bytes.length > 0) {
            principals = this.convertBytesToPrincipals(bytes, subjectContext);
        }
    } catch (RuntimeException var4) {
        principals = this.onRememberedPrincipalFailure(var4, subjectContext);
    }
    return principals;
}

2.2 密钥错误时的处理流程

当密钥错误时,解密过程会抛出异常:

  1. 进入 AbstractRememberMeManager#decrypt 方法
  2. 调用 cipherService.decrypt() 失败
  3. 抛出异常被 getRememberedPrincipals 捕获
  4. 执行 onRememberedPrincipalFailure 方法
  5. 最终调用 forgetIdentity 方法添加 deleteMe 标记

关键代码路径:

protected PrincipalCollection onRememberedPrincipalFailure(RuntimeException e, SubjectContext context) {
    // 日志记录
    this.forgetIdentity(context);
    throw e;
}

private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
    getCookie().removeFrom(request, response);
}

2.3 反序列化失败的处理

即使密钥正确,如果反序列化对象不符合要求,也会导致异常:

  1. convertBytesToPrincipals 调用 deserialize 方法
  2. 反序列化后尝试转换为 PrincipalCollection 类型
  3. 如果类型不匹配,抛出 ClassCastException
  4. 同样进入异常处理流程,添加 deleteMe 标记

0x03 创新检测方法原理

3.1 检测思路

基于上述分析,可以设计一种更可靠的检测方法,需满足两个条件:

  1. 构造一个继承 PrincipalCollection 的可序列化对象
  2. 确保密钥正确时不返回 deleteMe,错误时返回 deleteMe

3.2 关键实现类

SimplePrincipalCollection 类完美符合要求:

  • 实现了 Serializable 接口
  • 继承自 PrincipalCollection
  • 是 Shiro 内置类,兼容性有保障

0x04 检测工具实现

4.1 序列化对象构造

生成检测 payload 的 Java 代码:

SimplePrincipalCollection simplePrincipalCollection = new SimplePrincipalCollection();
ObjectOutputStream obj = new ObjectOutputStream(new FileOutputStream("payload"));
obj.writeObject(simplePrincipalCollection);
obj.close();

4.2 检测流程

  1. SimplePrincipalCollection 对象序列化
  2. 使用目标密钥进行 AES 加密
  3. 构造 rememberMe Cookie 发送请求
  4. 分析响应:
    • deleteMe:密钥正确
    • deleteMe:密钥错误

4.3 优势分析

相比传统方法,该技术具有:

  • 不依赖外部 DNSLOG
  • 不依赖特定 gadget 链
  • 误报率更低
  • 完全基于 Shiro 自身机制

0x05 防御建议

针对该检测方法,防御措施包括:

  1. 升级到最新 Shiro 版本
  2. 禁用 rememberMe 功能(如非必要)
  3. 使用自定义密钥而非默认密钥
  4. 实现 Web 应用防火墙规则过滤异常请求

0x06 总结

本文深入分析了 Shiro 反序列化漏洞的检测原理,提出了一种基于 SimplePrincipalCollection 的创新检测方法。该方法通过利用 Shiro 自身机制,实现了更准确、更可靠的密钥检测,为安全研究人员提供了新的技术思路。

Apache Shiro 反序列化漏洞检测技术深度解析 0x00 前言 Apache Shiro 是一个广泛使用的 Java 安全框架,其反序列化漏洞自2016年存在,但在近年攻防演练(HVV)中备受关注。本文将深入剖析 Shiro 的检测原理,并提出一种创新的检测方法,相比传统方式具有更高准确性和可靠性。 0x01 传统检测方法分析 1.1 常规检测方式 目前业界普遍采用的 Shiro 检测方法是在请求 Cookie 中添加 rememberMe=1 ,然后检查响应中是否出现 rememberMe=deleteMe 。这种方法的原理基于 Shiro 对 rememberMe 机制的处理流程。 1.2 传统方法的局限性 传统检测存在以下问题: 依赖 DNSLOG 进行外联验证 使用 Commons Collections 链进行盲测时可能存在误判 无法覆盖所有可能的 gadget 利用场景 0x02 Shiro 处理机制深度分析 2.1 核心处理流程 Shiro 对 rememberMe 的处理主要在 AbstractRememberMeManager#getRememberedPrincipals 方法中: 2.2 密钥错误时的处理流程 当密钥错误时,解密过程会抛出异常: 进入 AbstractRememberMeManager#decrypt 方法 调用 cipherService.decrypt() 失败 抛出异常被 getRememberedPrincipals 捕获 执行 onRememberedPrincipalFailure 方法 最终调用 forgetIdentity 方法添加 deleteMe 标记 关键代码路径: 2.3 反序列化失败的处理 即使密钥正确,如果反序列化对象不符合要求,也会导致异常: convertBytesToPrincipals 调用 deserialize 方法 反序列化后尝试转换为 PrincipalCollection 类型 如果类型不匹配,抛出 ClassCastException 同样进入异常处理流程,添加 deleteMe 标记 0x03 创新检测方法原理 3.1 检测思路 基于上述分析,可以设计一种更可靠的检测方法,需满足两个条件: 构造一个继承 PrincipalCollection 的可序列化对象 确保密钥正确时不返回 deleteMe ,错误时返回 deleteMe 3.2 关键实现类 SimplePrincipalCollection 类完美符合要求: 实现了 Serializable 接口 继承自 PrincipalCollection 是 Shiro 内置类,兼容性有保障 0x04 检测工具实现 4.1 序列化对象构造 生成检测 payload 的 Java 代码: 4.2 检测流程 将 SimplePrincipalCollection 对象序列化 使用目标密钥进行 AES 加密 构造 rememberMe Cookie 发送请求 分析响应: 无 deleteMe :密钥正确 有 deleteMe :密钥错误 4.3 优势分析 相比传统方法,该技术具有: 不依赖外部 DNSLOG 不依赖特定 gadget 链 误报率更低 完全基于 Shiro 自身机制 0x05 防御建议 针对该检测方法,防御措施包括: 升级到最新 Shiro 版本 禁用 rememberMe 功能(如非必要) 使用自定义密钥而非默认密钥 实现 Web 应用防火墙规则过滤异常请求 0x06 总结 本文深入分析了 Shiro 反序列化漏洞的检测原理,提出了一种基于 SimplePrincipalCollection 的创新检测方法。该方法通过利用 Shiro 自身机制,实现了更准确、更可靠的密钥检测,为安全研究人员提供了新的技术思路。