新型 tomcat websocket 内存马检测与防护思路探究
字数 1421 2025-08-12 11:33:58
Tomcat WebSocket 内存马检测与防护技术文档
1. WebSocket 内存马概述
1.1 基本概念
WebSocket 内存马是一种新型的 Tomcat 内存驻留型后门,与传统基于 Filter 或 Servlet 的内存马不同,它利用 WebSocket 协议实现隐蔽通信。
1.2 技术特点
- 基于 WebSocket 协议,通信更隐蔽
- 不依赖 Filter 或 Servlet 机制
- 常规内存马扫描工具(如 memshell scanner)无法检测
- 通过注解方式动态注册 WebSocket 端点
2. WebSocket 内存马实现原理
2.1 Tomcat WebSocket 注册机制
Tomcat 服务器启动时通过 WsSci 中的 WsServerContainer 完成以下操作:
- 扫描 classpath 下带有
@ServerEndpoint注解的类 - 将这些类加入到一个 iterator 中
- 遍历 iterator,为每个元素创建
ServerEndpointConfig - 通过
addEndpoint方法将类加入到 WebSocket 服务中
2.2 内存马注入流程
攻击者可以模拟上述流程,在运行时动态注入 WebSocket 端点:
- 动态创建带有
@ServerEndpoint注解的类 - 获取
WsServerContainer实例 - 创建
ServerEndpointConfig - 调用
addEndpoint方法注册恶意端点
3. WebSocket 内存马存储结构
3.1 核心存储位置
所有注册的 WebSocket 服务存储在 WsServerContainer 的私有成员变量中:
private final Map<String, ExactPathMatch> configExactMatchMap
3.2 数据结构解析
- Key: WebSocket 服务的 URL 路径
- Value:
WsServerContainer.ExactPathMatch对象- 包含
ServerEndpointConfig配置信息 - 其中
config变量存储了 WebSocket 服务的实体类
- 包含
4. 检测技术实现
4.1 检测原理
通过反射获取 WsServerContainer 的 configExactMatchMap,遍历其中所有已注册的 WebSocket 服务,检查是否存在可疑端点。
4.2 JSP 检测脚本实现
<%@ page import="org.apache.tomcat.websocket.server.WsServerContainer" %>
<%@ page import="javax.websocket.server.ServerContainer" %>
<%@ page import="java.lang.reflect.Field" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.Set" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="javax.websocket.server.ServerEndpointConfig" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 获取 WsServerContainer 实例
WsServerContainer wsServerContainer = (WsServerContainer) request.getServletContext()
.getAttribute(ServerContainer.class.getName());
// 反射获取私有变量 configExactMatchMap
Class<?> obj = Class.forName("org.apache.tomcat.websocket.server.WsServerContainer");
Field field = obj.getDeclaredField("configExactMatchMap");
field.setAccessible(true);
Map<String, Object> configExactMatchMap = (Map<String, Object>) field.get(wsServerContainer);
// 遍历并打印所有注册的 WebSocket 服务
Set<String> keyset = configExactMatchMap.keySet();
Iterator<String> iterator = keyset.iterator();
while (iterator.hasNext()){
String key = iterator.next();
Object object = wsServerContainer.findMapping(key);
Class<?> wsMappingResultObj = Class.forName("org.apache.tomcat.websocket.server.WsMappingResult");
Field configField = wsMappingResultObj.getDeclaredField("config");
configField.setAccessible(true);
ServerEndpointConfig config1 = (ServerEndpointConfig)configField.get(object);
Class<?> clazz = config1.getEndpointClass();
out.println(String.format("websocket name:%s, websocket class: %s", key, clazz.getName()));
}
// 删除指定 WebSocket 服务
if(request.getParameter("name")!= null){
configExactMatchMap.remove(request.getParameter("name"));
out.println(String.format("delete ws service: %s", request.getParameter("name")));
}
%>
5. 防护与清除方案
5.1 检测方案
- 定期执行检测脚本,检查所有注册的 WebSocket 端点
- 重点关注以下可疑特征:
- 非常规路径的 WebSocket 端点
- 类名为随机字符串或非常规命名的端点
- 非业务预期的 WebSocket 服务
5.2 清除方案
通过删除 configExactMatchMap 中对应的条目即可清除内存马:
configExactMatchMap.remove("恶意端点路径");
访问检测脚本时添加 ?name=恶意端点路径 参数即可删除指定服务。
6. 防御建议
- 权限控制:限制 Web 应用的部署权限
- 代码审计:检查所有带有
@ServerEndpoint注解的类 - 运行时监控:监控 WebSocket 端点的动态注册行为
- 安全加固:禁用不必要的 WebSocket 功能
- 定期扫描:使用专用工具或脚本定期扫描内存马