Apache Shiro 是 Java 领域使用极其广泛的开源安全框架,主要用于身份验证(Authentication)、授权(Authorization)、密码学(Cryptography)和会话管理(Session Management)。
然而,由于其过去在 Cookie 处理和反序列化机制上的设计缺陷,产生了网络安全史上非常经典的漏洞类型,如 Shiro 550(硬编码密钥反序列化) 和 Shiro 721(Padding Oracle 填充 oracle 攻击)。
一、 Shiro 核心运作机制:RememberMe
要理解 Shiro 的漏洞,首先需要理解 Shiro 的 RememberMe(记住我)功能是如何运作的。
当用户勾选 "RememberMe" 并成功登录时,Shiro 会在响应头中返回一个名为 rememberMe 的 Cookie。当用户再次发起请求时,Shiro 会读取该 Cookie 并按如下步骤还原用户身份:

漏洞正是在 步骤 2 和 3 中产生的。
二、 漏洞一:Shiro-550 (CVE-2016-4437) 密钥硬编码反序列化
1. 漏洞成因
在 Shiro <= 1.2.4 版本中,官方在 AbstractRememberMeManager 中硬编码了一个默认的 AES 密钥:
// kPH+bIxkYvoCFrQEkspM4A== 的 Base64 解码即为硬编码密钥
private static final byte[] DEFAULT_CIPHER_KEY_BYTES =
Base64.decode("kPH+bIxkYvoCFrQEkspM4A==");
由于加解密秘钥公开且固定,攻击者可以构造任意的恶意 Java 对象,用这个默认密钥按相同流程进行序列化 -> AES 加密 -> Base64 编码 ,然后放入 Cookie: rememberMe=... 发送给服务器。
服务器收到请求后,用默认密钥成功解密,并在第 3 步执行了 readObject() 反序列化,导致任意代码执行(RCE)。
2. 漏洞利用流程
**1.构造恶意 Java 对象:**使用 Ysoserial 生成结合目标依赖(如 CommonsCollections)的 Payload。
攻击者利用已知依赖链(Gadget)生成触发系统命令(如 calc 或反弹 Shell)的字节序列。
**2.AES 加密 Payload:**匹配 Shiro 的加密配置(默认 AES-CBC,IV 为 16 字节随机数)。
使用已知密钥(如 kPH+bIxkYvoCFrQEkspM4A==)对恶意序列化字节数组进行 AES 加密。
**3.Base64 编码:**符合 Cookie 传输规范。
将加密后的字节数组进行 Base64 编码,生成 Payload 字符串。
**4.发送请求注入:**带上 Header 发起请求。
在 HTTP 请求头中添加 Cookie: rememberMe=<Payload> 发送给目标系统。
**5.服务器触发漏洞:**目标解密并触发 readObject()。
目标服务器使用硬编码密钥成功解密 Cookie,并在执行反序列化时触发了恶意 Payload,执行攻击者命令。
三、 漏洞二:Shiro-721 (CVE-2019-12422) Padding Oracle 填充攻击
1. 漏洞成因
针对 Shiro 550,官方在 1.2.5 及后续更新中删除了硬编码密钥,改用每次启动随机生成 AES 密钥 。这看似解决了问题,但随后又暴露了 Shiro 721。
Shiro 在 CBC 模式下使用了 PKCS5Padding 填充,且未对密文进行适当的完整性校验(如 HMAC-SHA256):
-
当攻击者发送一个解密后填充格式不正确的 Cookie 时,服务端会返回
deleteMe。 -
当解密后填充格式正确,但反序列化失败时,服务端会返回不同的响应特征。
这种响应的差异形成了 Padding Oracle(填充提示侧信道)。
2. 漏洞利用流程
攻击者在不需要知道 AES 密钥 的前提下,只要能够获取到一个合法用户的正常 rememberMe Cookie,就可以通过向服务器发起成千上万次侧信道碰撞测试:
-
逐字节密文碰撞,利用服务端回显推导出明文的异或中间值(Intermediate Bytes)。
-
利用推导出的中间值,伪造出任意明文对应的合法加密密文。
-
将恶意反序列化 Payload 伪造加密后,发送给服务端,同样达成 RCE。
四、 实战利用与排查工具
在实际安全测试(渗透测试 / 红队演练)中,通常使用自动化工具快速定位与验证漏洞。
1. 常用利用工具
-
ShiroExploit / Shiro综合利用工具:集成了密钥爆破、Gadget 自动化匹配、一键命令执行、Memory Shell(内存马)注入等功能。
-
ysoserial:Java 反序列化 Payload 生成的核心神器。
2. 如何判断目标使用了 Shiro 框架?
-
响应头特征 :请求响应头中包含
Set-Cookie: rememberMe=deleteMe;。 -
主动触发 :故意在请求中带上
Cookie: rememberMe=1;,看服务器是否会在响应头中返回Set-Cookie: rememberMe=deleteMe;。
五、 常见的 Shiro 绕过与回显技术(红队进阶)
在现代防御体系下,仅凭执行简单命令可能无法直接获取权限,通常需要结合以下进阶技巧:
1. 无安全依赖下的 Gadget 选择
目标服务器上可能没有安装 CommonsCollections 等常见第三方库,此时红队通常会使用原生 JRE/JDK 自带的依赖链,如:
-
CommonsBeanutils -
ROME -
AspectJWeaver -
基于 JDK 原生的
JRMPClient盲打
2. 回显技术(Echo)与内存马(Memory Shell)
为了避免出网受限(如防火墙拦截反弹 Shell),利用利用链将 Spring / Tomcat 动态内存马(Filter/Servlet 内存马) 直接注入到目标 Java 虚拟机进程中,可以实现无需落地文件、无视出网限制的持久化控制。