Java内存马中的Servlet,Filter,Listener
字数 2585 2025-09-01 11:26:11

Java内存马技术深度解析:Servlet、Filter与Listener的实现与防御

一、内存马核心概念

1.1 内存马的本质

内存马(Memory Shell)是一种驻留在目标Java Web应用进程中的持久化、隐蔽后门,与传统Webshell相比具有以下特性:

  • "内存"特性:不依赖磁盘文件,恶意代码(类字节码)直接驻留在JVM内存中
  • 实现方式:通过运行时动态生成类(BCEL/ASM)、利用应用自身功能动态注册组件或篡改现有组件
  • "马"特性:伪装成或寄生在应用的合法部分(Servlet/Filter/Listener)
  • 持久化:依赖目标应用生存周期,应用不重启则持续有效

1.2 内存马的工作流程

  1. 监听特定请求路径或事件
  2. 解析请求中的加密/混淆指令
  3. 执行恶意操作(命令执行、文件操作、内存扫描等)
  4. 将结果返回给攻击者

二、Servlet内存马技术

2.1 Servlet的正常角色

Java EE中处理HTTP请求的核心组件,负责:

  • 接收请求
  • 处理业务逻辑
  • 生成响应

2.2 内存马实现原理

动态注册恶意Servlet

// 伪代码示例
ServletContext servletContext = request.getServletContext();
ServletRegistration.Dynamic registration = servletContext.addServlet(
    "MaliciousServletName", 
    new EvilServletClass()
);
registration.addMapping("/hidden-backdoor-path");
registration.setLoadOnStartup(1);

恶意代码注入点

主要存在于以下方法中:

  • service()
  • doGet()
  • doPost()

恶意逻辑包括:

  1. 检查请求中的"暗号"(特定参数/Header/Cookie)
  2. 解析加密/混淆的指令(如Base64编码的cmd参数)
  3. 执行指令(通过Runtime.exec()ProcessBuilder
  4. 加密/混淆执行结果并写入HTTP响应

2.3 特点分析

  • 直接性:最接近传统Webshell的实现方式
  • 路径唯一性:绑定到特定URL路径,可能被扫描器发现
  • 依赖容器API:需要访问ServletContext对象

三、Filter内存马技术

3.1 Filter的正常角色

在请求到达Servlet之前和响应发送给客户端之前执行预处理和后处理,用于:

  • 身份验证
  • 日志记录
  • 编码转换等

3.2 内存马实现原理

动态注册恶意Filter

// 伪代码示例
ServletContext servletContext = request.getServletContext();
FilterRegistration.Dynamic registration = servletContext.addFilter(
    "MaliciousFilterName", 
    new EvilFilterClass()
);
registration.addMappingForUrlPatterns(
    EnumSet.of(DispatcherType.REQUEST), 
    true, 
    "/*"
);
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);

恶意代码注入点

主要存在于doFilter()方法中:

  1. 检查每个请求是否包含"暗号"
  2. 匹配则:
    • 截获请求并执行恶意指令
    • 加密/混淆结果并通过HttpServletResponse输出
    • 中断Filter链(不调用chain.doFilter()
  3. 不匹配则正常放行请求

3.3 特点分析

  • 高隐蔽性:监听所有请求路径(/*),无需特定URL
  • 破坏链完整性:匹配恶意请求时中断链
  • 当前主流:最常见和危害最大的内存马类型之一

四、Listener内存马技术

4.1 Listener的正常角色

监听Web应用中的各种事件,包括:

  • ServletContext的创建/销毁
  • HttpSession的创建/销毁/属性变更
  • ServletRequest的创建/销毁

4.2 主要Listener类型及利用

4.2.1 ServletRequestListener

public void requestInitialized(ServletRequestEvent sre) {
    // 在每个请求开始时检查"暗号"
    // 执行恶意操作但不能直接回显
    // 结果存储在请求属性或ThreadLocal中
}

public void requestDestroyed(ServletRequestEvent sre) {
    // 请求结束时清理痕迹
}

4.2.2 ServletContextListener

public void contextInitialized(ServletContextEvent sce) {
    // Web应用启动时调用
    // 可动态注册其他类型内存马
}

public void contextDestroyed(ServletContextEvent sce) {
    // Web应用停止时调用
}

4.2.3 HttpSessionListener

public void sessionCreated(HttpSessionEvent se) {
    // 劫持所有会话
    // 植入会话木马
}

public void sessionDestroyed(HttpSessionEvent se) {
    // 清理会话相关资源
}

4.3 特点分析

  • 极高隐蔽性:无URL映射,仅监听事件
  • 多功能性
    • 作为其他内存马的"加载器"
    • 实现无文件持久化
    • 非回显利用(内存扫描、线程注入等)
  • 持久化关键contextInitialized方法可实现重启后自动重新注入

五、内存马注入技术详解

5.1 常见注入入口点

  1. 漏洞利用
    • RCE漏洞(反序列化、表达式注入等)
    • 文件上传漏洞
  2. 已有Webshell
  3. 中间件管理接口/配置错误

5.2 通过Fastjson反序列化注入

5.2.1 Servlet注入关键步骤

  1. 获取ServletContext

    ServletContext servletContext = request.getSession().getServletContext();
    // 通过反射获取StandardContext
    
  2. 动态注册恶意Servlet:

    ServletRegistration.Dynamic registration = context.addServlet(
        "LegitServletName", 
        new EvilServletClass()
    );
    registration.addMapping("/static/..;/admin/healthcheck");
    

5.2.2 Filter注入关键步骤

  1. 获取StandardContext

    // 通过线程类加载器获取
    WebappClassLoaderBase classLoader = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
    StandardContext stdCtx = (StandardContext) classLoader.getResources().getContext();
    
  2. 构造并注册恶意Filter:

    // 创建FilterDef
    FilterDef filterDef = new FilterDef();
    filterDef.setFilterName("LegitFilter");
    filterDef.setFilterClass(EvilFilter.class.getName());
    stdCtx.addFilterDef(filterDef);
    
    // 创建FilterMap
    FilterMap filterMap = new FilterMap();
    filterMap.setFilterName("LegitFilter");
    filterMap.addURLPattern("/*");
    stdCtx.addFilterMapBefore(filterMap);
    

5.2.3 Listener注入关键步骤

  1. 反射注册恶意Listener:
    // 获取applicationEventListenersList字段
    Field listenersField = StandardContext.class.getDeclaredField("applicationEventListenersList");
    listenersField.setAccessible(true);
    
    // 添加恶意监听器
    Object[] newListeners = Arrays.copyOf(currentListeners, currentListeners.length + 1);
    newListeners[currentListeners.length] = listener;
    

5.3 高级规避技术

  1. 路径混淆

    registration.addMapping("/a/../%3b/bypass");
    
  2. 内存加密

    byte[] bytecode = encrypt(evilServletBytes);
    Class<?> clazz = new CustomClassLoader().defineClass("com.legit.Utils", bytecode);
    
  3. 反检测机制

    if (System.getProperty("arthas") != null) {
        Thread.sleep(30000); // 延迟响应干扰扫描
    }
    

六、检测与防御方案

6.1 检测挑战

  • 无文件落地
  • 代码驻留内存
  • 利用合法API
  • 伪装性强

6.2 检测思路

  1. 运行时分析
    • 扫描注册组件(Servlet/Filter/Listener)
    • 检查类加载来源
  2. 字节码分析
    • 查找危险方法调用(Runtime.execdefineClass等)
  3. 行为监控
    • 异常网络连接
    • 敏感文件访问
    • HTTP请求/响应异常模式
  4. Agent/RASP
    • 监控类加载、方法执行、组件注册等

6.3 防御措施

  1. 基础防御

    • 及时修补漏洞
    • 最小权限原则
    • 安全配置(禁用不必要管理接口)
  2. 技术防护

    <!-- Tomcat禁用动态注册 -->
    <Context>
        <JarScanner scanClassPath="false" />
    </Context>
    
  3. 监控与响应

    • WAF/RASP部署
    • 安全基线与变更监控
    • 定期内存扫描

6.4 专项检测工具

  1. 内存扫描

    jcmd <PID> VM.classes | grep 'Filter'
    
  2. RASP检测示例

    public void addFilter(ServletContext ctx, String name, Filter filter) {
        if (filter.getClass().getName().contains("Evil")) {
            throw new SecurityException("Blocked malicious filter!");
        }
    }
    

七、技术演进与趋势

7.1 最新绕过技术

  1. GraalVM Native Image:编译Filter代码绕过类加载监控
  2. Project Loom:利用虚拟线程隐藏执行流
  3. eBPF层隐藏:在内核层面隐藏恶意线程

7.2 防御体系构建

三维防护策略

  1. 应用层:代码审计、SCA
  2. 容器层:配置加固、RASP
  3. 系统层:内存完整性校验、行为监控

八、总结对比

组件类型 核心注入点 隐蔽性关键 主要威胁方式 检测难点
Servlet service()/doGet()/doPost() 特定URL路径 通过特定URL路径执行指令 恶意路径枚举
Filter doFilter() 监听所有请求(/*) 拦截所有请求匹配暗号 无特定路径,需深度分析链
Listener requestInitialized(), contextInitialized() 无URL映射,监听事件 作为加载器、非回显操作 非常隐蔽,事件监听难察觉

防御Java内存马需要采取纵深防御策略,结合漏洞修补、运行时监控、行为分析和安全基线的综合手段。随着云原生技术的发展,内存马攻防将向更底层转移,要求安全团队掌握系统级防护能力。

Java内存马技术深度解析:Servlet、Filter与Listener的实现与防御 一、内存马核心概念 1.1 内存马的本质 内存马(Memory Shell)是一种驻留在目标Java Web应用进程中的持久化、隐蔽后门,与传统Webshell相比具有以下特性: "内存"特性 :不依赖磁盘文件,恶意代码(类字节码)直接驻留在JVM内存中 实现方式 :通过运行时动态生成类(BCEL/ASM)、利用应用自身功能动态注册组件或篡改现有组件 "马"特性 :伪装成或寄生在应用的合法部分(Servlet/Filter/Listener) 持久化 :依赖目标应用生存周期,应用不重启则持续有效 1.2 内存马的工作流程 监听特定请求路径或事件 解析请求中的加密/混淆指令 执行恶意操作(命令执行、文件操作、内存扫描等) 将结果返回给攻击者 二、Servlet内存马技术 2.1 Servlet的正常角色 Java EE中处理HTTP请求的核心组件,负责: 接收请求 处理业务逻辑 生成响应 2.2 内存马实现原理 动态注册恶意Servlet 恶意代码注入点 主要存在于以下方法中: service() doGet() doPost() 恶意逻辑包括: 检查请求中的"暗号"(特定参数/Header/Cookie) 解析加密/混淆的指令(如Base64编码的 cmd 参数) 执行指令(通过 Runtime.exec() 或 ProcessBuilder ) 加密/混淆执行结果并写入HTTP响应 2.3 特点分析 直接性 :最接近传统Webshell的实现方式 路径唯一性 :绑定到特定URL路径,可能被扫描器发现 依赖容器API :需要访问 ServletContext 对象 三、Filter内存马技术 3.1 Filter的正常角色 在请求到达Servlet之前和响应发送给客户端之前执行预处理和后处理,用于: 身份验证 日志记录 编码转换等 3.2 内存马实现原理 动态注册恶意Filter 恶意代码注入点 主要存在于 doFilter() 方法中: 检查每个请求是否包含"暗号" 匹配则: 截获请求并执行恶意指令 加密/混淆结果并通过 HttpServletResponse 输出 中断Filter链(不调用 chain.doFilter() ) 不匹配则正常放行请求 3.3 特点分析 高隐蔽性 :监听所有请求路径( /* ),无需特定URL 破坏链完整性 :匹配恶意请求时中断链 当前主流 :最常见和危害最大的内存马类型之一 四、Listener内存马技术 4.1 Listener的正常角色 监听Web应用中的各种事件,包括: ServletContext 的创建/销毁 HttpSession 的创建/销毁/属性变更 ServletRequest 的创建/销毁 4.2 主要Listener类型及利用 4.2.1 ServletRequestListener 4.2.2 ServletContextListener 4.2.3 HttpSessionListener 4.3 特点分析 极高隐蔽性 :无URL映射,仅监听事件 多功能性 : 作为其他内存马的"加载器" 实现无文件持久化 非回显利用(内存扫描、线程注入等) 持久化关键 : contextInitialized 方法可实现重启后自动重新注入 五、内存马注入技术详解 5.1 常见注入入口点 漏洞利用 : RCE漏洞(反序列化、表达式注入等) 文件上传漏洞 已有Webshell 中间件管理接口/配置错误 5.2 通过Fastjson反序列化注入 5.2.1 Servlet注入关键步骤 获取 ServletContext : 动态注册恶意Servlet: 5.2.2 Filter注入关键步骤 获取 StandardContext : 构造并注册恶意Filter: 5.2.3 Listener注入关键步骤 反射注册恶意Listener: 5.3 高级规避技术 路径混淆 : 内存加密 : 反检测机制 : 六、检测与防御方案 6.1 检测挑战 无文件落地 代码驻留内存 利用合法API 伪装性强 6.2 检测思路 运行时分析 : 扫描注册组件(Servlet/Filter/Listener) 检查类加载来源 字节码分析 : 查找危险方法调用( Runtime.exec 、 defineClass 等) 行为监控 : 异常网络连接 敏感文件访问 HTTP请求/响应异常模式 Agent/RASP : 监控类加载、方法执行、组件注册等 6.3 防御措施 基础防御 : 及时修补漏洞 最小权限原则 安全配置(禁用不必要管理接口) 技术防护 : 监控与响应 : WAF/RASP部署 安全基线与变更监控 定期内存扫描 6.4 专项检测工具 内存扫描 : RASP检测示例 : 七、技术演进与趋势 7.1 最新绕过技术 GraalVM Native Image :编译Filter代码绕过类加载监控 Project Loom :利用虚拟线程隐藏执行流 eBPF层隐藏 :在内核层面隐藏恶意线程 7.2 防御体系构建 三维防护策略 : 应用层 :代码审计、SCA 容器层 :配置加固、RASP 系统层 :内存完整性校验、行为监控 八、总结对比 组件类型 | 核心注入点 | 隐蔽性关键 | 主要威胁方式 | 检测难点 ---|---|---|---|--- Servlet | service()/doGet()/doPost() | 特定URL路径 | 通过特定URL路径执行指令 | 恶意路径枚举 Filter | doFilter() | 监听所有请求(/* ) | 拦截所有请求匹配暗号 | 无特定路径,需深度分析链 Listener | requestInitialized(), contextInitialized() | 无URL映射,监听事件 | 作为加载器、非回显操作 | 非常隐蔽,事件监听难察觉 防御Java内存马需要采取纵深防御策略,结合漏洞修补、运行时监控、行为分析和安全基线的综合手段。随着云原生技术的发展,内存马攻防将向更底层转移,要求安全团队掌握系统级防护能力。