docs: add some highlights

This commit is contained in:
ReaJason
2026-01-18 23:49:41 +08:00
parent 5b0305be37
commit 0296705a87
2 changed files with 15 additions and 11 deletions
@@ -50,7 +50,7 @@ public class ExampleEndpoint extends Endpoint {
} }
``` ```
接口继承 javax.websocket.Endpoint,在 onOpen 的时候注册消息处理器。 通过继承 `javax.websocket.Endpoint` 类,在 `onOpen` 方法中注册消息处理器。
在内存马场景下,可以在 onMessage 方法中添加恶意逻辑,例如执行系统命令或加载其他恶意代码,以下是命令回显 WebSocket Endpoint 示例: 在内存马场景下,可以在 onMessage 方法中添加恶意逻辑,例如执行系统命令或加载其他恶意代码,以下是命令回显 WebSocket Endpoint 示例:
@@ -129,7 +129,7 @@ public class WsSci implements ServletContainerInitializer {
Set<ServerEndpointConfig> filteredEndpointConfigs = ...; Set<ServerEndpointConfig> filteredEndpointConfigs = ...;
try { try {
for (ServerEndpointConfig config : filteredEndpointConfigs) { for (ServerEndpointConfig config : filteredEndpointConfigs) {
sc.addEndpoint(config); sc.addEndpoint(config); // [!code highlight]
} }
// ... // ...
} catch (DeploymentException e) { } catch (DeploymentException e) {
@@ -139,7 +139,7 @@ public class WsSci implements ServletContainerInitializer {
static WsServerContainer init(ServletContext servletContext, boolean initBySciMechanism) { static WsServerContainer init(ServletContext servletContext, boolean initBySciMechanism) {
WsServerContainer sc = new WsServerContainer(servletContext); WsServerContainer sc = new WsServerContainer(servletContext);
servletContext.setAttribute("javax.websocket.server.ServerContainer", sc); servletContext.setAttribute("javax.websocket.server.ServerContainer", sc); // [!code highlight]
// ... // ...
return sc; return sc;
} }
@@ -204,7 +204,7 @@ sec-websocket-key = 4yY8pZQPUv6RlRoPgh7SaA==
sec-websocket-extensions = permessage-deflate; client_max_window_bits sec-websocket-extensions = permessage-deflate; client_max_window_bits
``` ```
实现细节的话,不知道大家有没有注意到 Tomcat 中总是默认注册个 Filter 叫作 `org.apache.tomcat.websocket.server.WsFilter`,其实这个就是用于将 HTTP 请求升级为 WebSocket 协议的 Filter 实现细节上,Tomcat 默认注册一个名为 `org.apache.tomcat.websocket.server.WsFilter` 的 Filter用于将 HTTP 请求升级为 WebSocket 协议。
首先会在 `UpgradeUtil.isWebSocketUpgradeRequest` 判断请求头里面有没有 `Upgrade: websocket` 以及是不是 GET 请求。 首先会在 `UpgradeUtil.isWebSocketUpgradeRequest` 判断请求头里面有没有 `Upgrade: websocket` 以及是不是 GET 请求。
其次在 `UpgradeUtil.doUpgrade` 方法中会检查 `Connection: upgrade` 以及 `Sec-WebSocket-Version: 13`,如果没有这些头部就会直接返回 400 或 426 错误码。 其次在 `UpgradeUtil.doUpgrade` 方法中会检查 `Connection: upgrade` 以及 `Sec-WebSocket-Version: 13`,如果没有这些头部就会直接返回 400 或 426 错误码。
@@ -239,15 +239,15 @@ public class UpgradeUtil {
public static boolean isWebSocketUpgradeRequest(ServletRequest request, ServletResponse response) { public static boolean isWebSocketUpgradeRequest(ServletRequest request, ServletResponse response) {
return request instanceof HttpServletRequest return request instanceof HttpServletRequest
&& response instanceof HttpServletResponse && response instanceof HttpServletResponse
&& headerContainsToken((HttpServletRequest)request, "Upgrade", "websocket") && headerContainsToken((HttpServletRequest)request, "Upgrade", "websocket") // [!code highlight]
&& "GET".equals(((HttpServletRequest)request).getMethod()); && "GET".equals(((HttpServletRequest)request).getMethod());
} }
public static void doUpgrade(WsServerContainer sc, HttpServletRequest req, HttpServletResponse resp, ServerEndpointConfig sec, Map<String, String> pathParams) throws ServletException, IOException { public static void doUpgrade(WsServerContainer sc, HttpServletRequest req, HttpServletResponse resp, ServerEndpointConfig sec, Map<String, String> pathParams) throws ServletException, IOException {
String subProtocol = null; String subProtocol = null;
if (!headerContainsToken(req, "Connection", "upgrade")) { if (!headerContainsToken(req, "Connection", "upgrade")) { // [!code highlight]
resp.sendError(400); resp.sendError(400);
} else if (!headerContainsToken(req, "Sec-WebSocket-Version", "13")) { } else if (!headerContainsToken(req, "Sec-WebSocket-Version", "13")) { // [!code highlight]
resp.setStatus(426); resp.setStatus(426);
resp.setHeader("Sec-WebSocket-Version", "13"); resp.setHeader("Sec-WebSocket-Version", "13");
} }
@@ -256,7 +256,7 @@ public class UpgradeUtil {
} }
``` ```
结合上面过 Nginx Tomcat 拿到的请求头,我们缺失的就是 `Upgrade: websocket` 和 `Connection: upgrade` 这两个请求头,使得请求根本没进入 WsFilter 的逻辑导致连接失败。所以我们需要伪造一个类似 WsFilter 的组件并且处理缺失的请求头,我根据 Filter 和 Valve 的注入代码量,选择了更轻量化的 Valve 组件: 结合上面过 Nginx 转发到 Tomcat 的请求头,可以看到缺失的就是 `Upgrade: websocket` 和 `Connection: upgrade` 这两个请求头,导致请求无法进入 WsFilter 的逻辑从而连接失败。因此我们需要创建一个类似 WsFilter 的组件来补充缺失的请求头。考虑到 Filter 和 Valve 的注入代码量,这里选择了更轻量化的 Valve 组件:
```java ```java
public class TomcatWsBypassValve implements Valve { public class TomcatWsBypassValve implements Valve {
@@ -369,3 +369,7 @@ private void inject(Object context, Object obj) throws Exception {
invokeMethod(container, "addEndpoint", new Class[]{serverEndpointConfigClass}, new Object[]{endpointConfig}); invokeMethod(container, "addEndpoint", new Class[]{serverEndpointConfigClass}, new Object[]{endpointConfig});
} }
``` ```
## 相关文档
- [Command 内存马使用教程](/docs/shelltool/command) - 了解如何生成和使用 WebSocket 命令执行内存马
+1 -1
View File
@@ -59,7 +59,7 @@ Connected (press CTRL+C to quit)
`/app` 是应用的路径,`/ws-bypass-cmd` 是上述生成时填的路径。 `/app` 是应用的路径,`/ws-bypass-cmd` 是上述生成时填的路径。
我们可以先尝试直接连接,直接 404 因为 /app/ws-bypass-cmd 并不存在。 我们可以先尝试直接连接,会返回 404 错误,因为 `/app/ws-bypass-cmd` 路径并不存在。
```bash ```bash
wscat -c ws://127.0.0.1/app/ws-bypass-cmd wscat -c ws://127.0.0.1/app/ws-bypass-cmd