Tomcat内存马原理如何为?
摘要:原理分析 | Valve —— Tomcat 特有内存马 Tomcat 特有,比 Filter 更底层、更隐蔽。 目录 一、什么是 Valve? 二、Pipeline 是什么? 三、Valve 在 Pipeline 中是&q
原理分析 | Valve —— Tomcat 特有内存马
Tomcat 特有,比 Filter 更底层、更隐蔽。
目录
一、什么是 Valve?
二、Pipeline 是什么?
三、Valve 在 Pipeline 中是"单向链表"
四、Valve 与 Filter 的关键区别
五、静态注册 Valve
六、动态注入(内存马核心)
七、Valve 的层级扩展(Engine / Host 级别注入)
八、四种内存马对比总结
总结
一、什么是 Valve?
Valve 是 Tomcat Pipeline-Valve 管道机制的一部分,属于 Tomcat 特有的概念,不属于 Servlet 规范。
类比:请求处理的"高速公路收费口"
为了方便理解这几种内存马的层级关系,用高速公路来类比一下:
Listener:像高速公路入口的感应线圈(车一过就记录,不干预)。
Filter:像安检闸机(可以拦车、检查、放行)。
Valve:像高速公路上的隧道阀门,位于整个系统的最底层,所有车都必须经过它,而且它可以修改车的路线甚至把车"吞掉"。
每个容器(Engine / Host / Context / Wrapper) 都有自己的 Pipeline,里面可以添加多个 Valve。
二、Pipeline 是什么?
一句话解释:Pipeline 是 Tomcat 容器内部的一个处理链,里面可以按顺序放多个 Valve(阀门),请求会像水流一样依次流过这些阀门。
每个容器实例(Engine、Host、Context、Wrapper)都有一个 Pipeline 对象,这是 Tomcat 架构的固定设计。
即使不添加任何自定义 Valve,Pipeline 也至少包含一个 基础阀门(basic),用于完成容器的核心任务(比如调用子容器、处理 Servlet)。
可以通过 pipeline.addValve(valve) 添加任意多个自定义 Valve,它们会按照添加顺序依次执行(先添加的先执行)。
请求的大致流转路径是:Engine → Host → Context → Wrapper 的 Valve 管道,最后才到 Servlet。也正因为如此,Valve 比 Filter 更早触发(在 Context 级别甚至更早),而且可以拦截所有请求(包括静态资源、404 等),不需要任何 URL 映射。
Filter、Servlet、Listener 都属于 Context 级别(即一个 Web 应用内部),而 Valve 可以加在 Engine、Host、Context、Wrapper 任意一层。
三、Valve 在 Pipeline 中是"单向链表"
请求 → [Valve A] → [Valve B] → [Valve C] → [基础阀门] → Servlet
需要注意的点:
每个 Valve 的 invoke 方法中必须调用 getNext().invoke(request, response),否则请求链会中断(后面的 Valve 和 Servlet 都不会执行)。这个和 Filter 里的 chain.doFilter(request, response) 作用一模一样。
添加过多 Valve 会影响性能,但内存马场景一般只加 1 个。
Valve 是全局生效的:添加到 Engine 的 Valve 会影响所有 Host 下的所有应用;添加到 Context 的 Valve 只影响当前 Web 应用。
拿到容器的 Pipeline 对象(通过反射获取 StandardContext、StandardHost 等),就可以直接调用 addValve() 方法,而且该方法通常是 public 的,不需要反射破解。
四、Valve 与 Filter 的关键区别
特性
Valve
Filter
是否 Servlet 规范
❌ Tomcat 特有
✅ 规范定义
触发层级
容器级(Engine/Host/Context)
应用级(Context 内)
能否跨 Web 应用
能(Engine/Host 级别 Valve 可影响所有应用)
不能(只拦截注册的应用)
需要映射 URL 模式
否(自动全局拦截)
是(需配置 /* 等)
隐蔽性
更高(不常见于检测规则)
较高(但已是重点查杀对象)
五、静态注册 Valve
静态注册是 Tomcat 管理员配置全局功能的标准方式,不需要写任何 Java 代码(除了 Valve 实现类本身)。先搞清楚静态注册的流程,对后面理解动态注入也有帮助。
