Skip to content

Commit 7e13d3b

Browse files
committed
feat: add jsp unicode packer
1 parent effe8e1 commit 7e13d3b

File tree

6 files changed

+136
-7
lines changed

6 files changed

+136
-7
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,16 +400,16 @@ public static MemShellResult generate(String urlPattern, String server, String s
400400

401401
public static void injectIsOk(String url, String shellType, String shellTool, String content, Packers packer, GenericContainer<?> container) {
402402
switch (packer) {
403-
case JSP, ClassLoaderJSP, DefineClassJSP -> {
403+
case JSP, ClassLoaderJSP, ClassLoaderJSPUnicode, DefineClassJSP, DefineClassJSPUnicode -> {
404404
String uploadEntry = url + "/upload";
405405
String filename = shellType + shellTool + packer + ".jsp";
406406
String shellUrl = url + "/" + filename;
407407
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
408408
VulTool.urlIsOk(shellUrl);
409409
}
410-
case JSPX -> {
410+
case JSPX, JSPXUnicode -> {
411411
String uploadEntry = url + "/upload";
412-
String filename = shellType + shellTool + ".jspx";
412+
String filename = shellType + shellTool + packer + ".jspx";
413413
String shellUrl = url + "/" + filename;
414414
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
415415
VulTool.urlIsOk(shellUrl);

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
import com.reajason.javaweb.packer.jar.*;
2424
import com.reajason.javaweb.packer.jexl.JEXLPacker;
2525
import com.reajason.javaweb.packer.jinjava.JinJavaPacker;
26-
import com.reajason.javaweb.packer.jsp.ClassLoaderJspPacker;
27-
import com.reajason.javaweb.packer.jsp.DefineClassJspPacker;
28-
import com.reajason.javaweb.packer.jsp.JspPacker;
29-
import com.reajason.javaweb.packer.jsp.JspxPacker;
26+
import com.reajason.javaweb.packer.jsp.*;
3027
import com.reajason.javaweb.packer.jxpath.JXPathPacker;
3128
import com.reajason.javaweb.packer.jxpath.JXPathScriptEnginePacker;
3229
import com.reajason.javaweb.packer.jxpath.JXPathSpringGzipJDK17Packer;
@@ -79,8 +76,11 @@ public enum Packers {
7976
*/
8077
JSP(new JspPacker()),
8178
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
79+
ClassLoaderJSPUnicode(new ClassLoaderJspUnicodePacker(), JspPacker.class),
8280
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
81+
DefineClassJSPUnicode(new DefineClassJspUnicodePacker(), JspPacker.class),
8382
JSPX(new JspxPacker(), JspPacker.class),
83+
JSPXUnicode(new JspxUnicodePacker(), JspPacker.class),
8484

8585
/**
8686
* BigInteger
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.reajason.javaweb.packer.jsp;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import com.reajason.javaweb.packer.Packers;
6+
7+
public class ClassLoaderJspUnicodePacker implements Packer {
8+
@Override
9+
public String pack(ClassPackerConfig classPackerConfig) {
10+
return JspUnicoder.encode(Packers.ClassLoaderJSP.getInstance().pack(classPackerConfig), true);
11+
}
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.reajason.javaweb.packer.jsp;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import com.reajason.javaweb.packer.Packers;
6+
import com.reajason.javaweb.packer.Util;
7+
import lombok.SneakyThrows;
8+
9+
/**
10+
* @author ReaJason
11+
* @since 2024/11/26
12+
*/
13+
public class DefineClassJspUnicodePacker implements Packer {
14+
15+
@Override
16+
@SneakyThrows
17+
public String pack(ClassPackerConfig config) {
18+
return JspUnicoder.encode(Packers.DefineClassJSP.getInstance().pack(config), true);
19+
}
20+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.reajason.javaweb.packer.jsp;
2+
3+
import org.apache.commons.codec.binary.Hex;
4+
5+
import java.nio.charset.StandardCharsets;
6+
7+
public class JspUnicoder {
8+
9+
public static String encode(String content, boolean isJsp) {
10+
if (content == null) {
11+
return null;
12+
}
13+
StringBuilder result = new StringBuilder(content.length());
14+
int lineStart = 0;
15+
int length = content.length();
16+
for (int i = 0; i < length; i++) {
17+
if (content.charAt(i) == '\n') {
18+
appendEncodedLine(result, content.substring(lineStart, i), isJsp);
19+
result.append('\n');
20+
lineStart = i + 1;
21+
}
22+
}
23+
if (lineStart <= length) {
24+
appendEncodedLine(result, content.substring(lineStart), isJsp);
25+
}
26+
return result.toString();
27+
}
28+
29+
private static void appendEncodedLine(StringBuilder output, String line, boolean isJsp) {
30+
if (shouldSkipLine(line, isJsp)) {
31+
output.append(line);
32+
return;
33+
}
34+
if (line.contains("page import") || line.contains("page pageEncoding") || line.contains("page contentType")) {
35+
int firstQuote = line.indexOf('"');
36+
int lastQuote = line.lastIndexOf('"');
37+
if (firstQuote != -1 && lastQuote > firstQuote) {
38+
String oldStr = line.substring(firstQuote + 1, lastQuote);
39+
String encoded = encodeWordChars(oldStr);
40+
output.append(line, 0, firstQuote + 1)
41+
.append(encoded)
42+
.append(line.substring(lastQuote));
43+
return;
44+
}
45+
}
46+
output.append(encodeWordChars(line));
47+
}
48+
49+
private static boolean shouldSkipLine(String line, boolean isJsp) {
50+
if (line == null) {
51+
return false;
52+
}
53+
if (!isJsp && (line.contains("jsp:root")
54+
|| line.contains("jsp:declaration")
55+
|| line.contains("jsp:scriptlet")
56+
|| line.contains("jsp:directive.page"))) {
57+
return true;
58+
}
59+
return false;
60+
}
61+
62+
private static String encodeWordChars(String input) {
63+
StringBuilder encoded = new StringBuilder(input.length() * 4);
64+
for (int i = 0; i < input.length(); i++) {
65+
char ch = input.charAt(i);
66+
if (isWordChar(ch)) {
67+
encoded.append(toUnicodeEscape(ch));
68+
} else {
69+
encoded.append(ch);
70+
}
71+
}
72+
return encoded.toString();
73+
}
74+
75+
private static boolean isWordChar(char ch) {
76+
return Character.isLetterOrDigit(ch) || ch == '_';
77+
}
78+
79+
private static String toUnicodeEscape(char ch) {
80+
byte[] bytes = String.valueOf(ch).getBytes(StandardCharsets.UTF_8);
81+
return "\\u00" + Hex.encodeHexString(bytes);
82+
}
83+
}
84+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.reajason.javaweb.packer.jsp;
2+
3+
import com.reajason.javaweb.packer.ClassPackerConfig;
4+
import com.reajason.javaweb.packer.Packer;
5+
import com.reajason.javaweb.packer.Packers;
6+
7+
public class JspxUnicodePacker implements Packer {
8+
@Override
9+
public String pack(ClassPackerConfig classPackerConfig) {
10+
String content = Packers.JSPX.getInstance().pack(classPackerConfig);
11+
return JspUnicoder.encode(content, false);
12+
}
13+
}

0 commit comments

Comments
 (0)