1. 内存马与Filter机制基础概念
在Web安全领域,内存马(Memory Shell)是一种驻留在服务器内存中的恶意后门程序。与传统webshell不同,它不依赖磁盘文件,直接通过内存加载执行,具有极强的隐蔽性。其中基于Filter的内存马是当前攻防对抗中的热点技术。
Filter是Java Servlet规范中的重要组件,本质是一个实现了javax.servlet.Filter接口的类。它的核心功能是对请求进行预处理和后处理,典型应用场景包括:
- 权限验证
- 日志记录
- 编码转换
- 数据压缩
Filter的工作流程可以简化为:
code复制客户端请求 -> FilterChain -> Servlet -> FilterChain -> 响应输出
这种设计模式使得攻击者可以通过动态注册恶意Filter来拦截所有请求,这也是Filter型内存马的技术基础。
注意:本文仅讨论防御技术原理,所有技术细节均以防护为目的展开
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Filter型内存马的工作原理
2.1 动态注册机制
攻击者利用Java反射和JNDI注入等技术,在不重启服务的情况下动态向Servlet容器注册恶意Filter。关键代码逻辑通常包括:
java复制// 获取标准上下文
ServletContext servletContext = request.getServletContext();
Field appctx = servletContext.getClass().getDeclaredField("context");
appctx.setAccessible(true);
ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
// 获取FilterConfig
Field stdctx = applicationContext.getClass().getDeclaredField("context");
stdctx.setAccessible(true);
StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
// 创建恶意Filter
Filter evilFilter = new EvilFilter();
FilterDef filterDef = new FilterDef();
filterDef.setFilter(evilFilter);
filterDef.setFilterName("evilFilter");
standardContext.addFilterDef(filterDef);
// 创建Filter映射
FilterMap filterMap = new FilterMap();
filterMap.addURLPattern("/*");
filterMap.setFilterName("evilFilter");
standardContext.addFilterMap(filterMap);
2.2 内存驻留特点
与传统webshell相比,Filter内存马具有:
- 无文件落地:不依赖jsp/aspx等脚本文件
- 高隐蔽性:常规文件扫描无法检测
- 高持久性:服务重启后可能仍然存在
- 全请求拦截:通过"/*"模式捕获所有请求
3. 检测与防御方案
3.1 运行时检测技术
通过Java Instrumentation API实现内存扫描:
java复制public class FilterDetector {
public static void scan() {
WebappClassLoaderBase classLoader =
(WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext context = classLoader.getResources().getContext();
// 检查已注册Filter
FilterDef[] filterDefs = context.findFilterDefs();
for (FilterDef def : filterDefs) {
if(isMalicious(def.getFilterClass())) {
alert(def.getFilterName());
}
}
// 检查Filter映射
FilterMap[] filterMaps = context.findFilterMaps();
for (FilterMap map : filterMaps) {
if("/*".equals(map.getURLPattern())) {
audit(map.getFilterName());
}
}
}
}
3.2 防御加固措施
- Filter白名单机制:
xml复制<!-- 在web.xml中配置 -->
<filter-mapping>
<filter-name>securityFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
- JVM安全参数:
code复制-Djava.security.manager
-Djava.security.policy==/path/to/security.policy
- RASP防护:部署运行时应用自保护系统,监控关键API调用:
- ClassLoader.defineClass()
- FilterRegistration.addMappingForUrlPatterns()
- StandardContext.addFilterDef()
4. 实战排查案例
4.1 异常Filter识别特征
通过对比分析正常和恶意Filter的特征差异:
| 特征项 | 正常Filter | 恶意Filter |
|---|---|---|
| 类加载路径 | /WEB-INF/classes | JNDI注入或内存生成 |
| URL模式 | 具体路径 | /* |
| Filter顺序 | 业务逻辑决定 | 刻意设置为最高优先级 |
| 类名 | 符合业务命名规范 | 随机字符串或仿冒合法名称 |
4.2 排查工具链
- Arthas诊断工具:
bash复制# 查看所有Filter
sc -d *Filter
# 查看类加载路径
jad com.example.EvilFilter
# 监控Filter调用
monitor -c 5 javax.servlet.Filter doFilter
- 内存分析工具:
- Eclipse MAT:分析heap dump中的Filter实例
- JDK Mission Control:实时监控Filter调用栈
5. 防护体系建议
5.1 分层防御架构
code复制 ┌─────────────────┐
│ 网络层防护 │ ← WAF/IPS/IDS
└────────┬────────┘
↓
┌─────────────────┐
│ 主机层防护 │ ← HIDS/文件监控
└────────┬────────┘
↓
┌─────────────────┐
│ 运行时防护 │ ← RASP/Java Security
└────────┬────────┘
↓
┌─────────────────┐
│ 应用层防护 │ ← Filter白名单/审计
└─────────────────┘
5.2 关键防护点
- 类加载控制:
java复制// 自定义SecurityManager
public class FilterSecurityManager extends SecurityManager {
public void checkCreateClassLoader() {
if(StackWalker.getInstance().walk(frames ->
frames.anyMatch(f -> f.getClassName().contains("Filter")))) {
throw new SecurityException("Filter class loading restricted");
}
}
}
- Filter注册审计:
java复制public class FilterAuditValve extends ValveBase {
@Override
public void invoke(Request request, Response response) {
StandardContext context = (StandardContext) getContainer();
context.addLifecycleListener(event -> {
if (event.getType().equals("afterAddFilter")) {
logSecurityEvent(event.getData());
}
});
getNext().invoke(request, response);
}
}
在实际运维中,我们发现内存马的防御需要建立动态的防御体系。我个人的经验是定期(建议每周)执行以下检查流程:
- 基线对比:保存合法的Filter配置快照,定期执行diff
- 堆内存扫描:使用MAT工具分析Filter实例的引用链
- 行为监控:对匹配"/*"的Filter进行请求采样审计
- 类加载监控:特别关注非/WEB-INF路径加载的Filter类
最后需要提醒的是,防御方需要保持对新型攻击手法的持续跟踪。最近出现的结合Jakarta EE和模块化系统的变种内存马,就需要更新检测规则才能有效应对。
