如何将Servlet原理与Tomcat内存马技术结合为?

摘要:代码审计 | Servlet —— Tomcat 内存马 系列:Tomcat 内存马 —— 继 Filter 型之后,聊聊 Servlet 型的动态注入。 目录 一、Servlet 是如何注册和工作的 二、Filter 和 Servlet
代码审计 | Servlet —— Tomcat 内存马 系列:Tomcat 内存马 —— 继 Filter 型之后,聊聊 Servlet 型的动态注入。 目录 一、Servlet 是如何注册和工作的 二、Filter 和 Servlet 的区别 三、回顾对比:Filter 型 vs Servlet 型 四、前置知识:Servlet 动态注册 API 五、直接调用 addServlet 的问题 六、Servlet 型内存马注入代码(反射绕过) 七、验证步骤 八、注意事项 九、总结 一、Servlet 是如何注册和工作的 先来看一个最基础的 Servlet 示例,路径:src/main/java/org/example/filter/EchoServlet.java package org.example.filter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; //@WebServlet(value = "/echo", loadOnStartup = 1) @WebServlet("/echo") public class EchoServlet extends HttpServlet { @Override public void init() throws ServletException { System.out.println("EchoServlet 初始化"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { String msg = req.getParameter("msg"); resp.setContentType("text/plain;charset=UTF-8"); resp.getWriter().write("你输入的是:" + msg); } @Override public void destroy() { System.out.println("EchoServlet 销毁"); } } 关于 loadOnStartup(懒加载) @WebServlet(value = "/echo", loadOnStartup = 1) 里面有个懒加载的知识点: loadOnStartup 默认是 -1,启用懒加载模式 规定 loadOnStartup >= 0 时,Tomcat 启动时就会加载这个 Servlet 懒加载模式下,只有第一次请求触发时才会初始化 init() 关闭懒加载后效果和 Filter 一样,启动服务时就初始化 注意:动态注册的 Servlet 默认也是懒加载(首次访问时才调用 init()),但在内存马场景中,我们通常会在注入后立即主动访问一次后门路径来激活它,因此懒加载并不影响使用。 启动服务后可以看到初始化的打印: 访问 http://localhost:8080/echo?msg=你好: 关闭时触发销毁: 二、Filter 和 Servlet 的区别 Filter 和 Servlet 最大的区别在于: Filter 是"中间拦截器",负责预处理和后处理,通过 chain.doFilter() 继续传递请求,请求最终要到达 Servlet Servlet 是"终点处理器",负责生成最终的响应内容 设置 @WebServlet("/echo") 后,访问 /echo 就会由这个 Servlet 处理。 如果设置 @WebServlet("/*"),那么不管访问 /xxxx 什么路径都会由这个 Servlet 处理。比如访问 http://localhost:8080/asdasd?msg=aaa: 依然可以正确显示内容,并没有 404,因为符合通配符规则。
阅读全文