JAVA安全-基于tomcat的内存马学习-基础
环境搭建这里可以去观看Drunkbaby大神的搭建教程链接基础Java Web 三大件,也就是 Servlet,Filter,Listener.当 Tomcat 接收到请求时候,依次会经过 Liste 2025-11-25 10:34:59 Author: www.freebuf.com(查看原文) 阅读量:1 收藏

环境搭建

这里可以去观看Drunkbaby大神的搭建教程链接
图片.png
image

基础

Java Web 三大件,也就是 Servlet,Filter,Listener.当 Tomcat 接收到请求时候,依次会经过 Listener -> Filter -> Servlet
Servlet主要用于响应浏览器发送的请求数据
Filter主要用于对浏览器发送给Servlet的请求数据进行过滤
Listener主要用于监听域对象的行为

Servlet

上文提及了Servlet主要是用于处理用户的请求并且做出响应,流程如下
image
demo

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

@WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
    private String message;

    public void init() {
        message = "Hello World!";
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");

        // Hello
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>" + message + "</h1>");
        out.println("</body></html>");
    }

    public void destroy() {
    }

顺带解释下@WebServlet(name = "helloServlet", value = "/hello-servlet"),说了是处理用户的请求,那么实际的开发肯定是不同的路径对应了不同的服务,如这里对应的就是当客户访问/hello-servlet路径时,调用名为helloServlet的Servlet来处理用户请求,可以看到
该Servelet继承了HttpServlet.通过名字就可以看出其是处理http请求的.doGet表明了其处理逻辑,即收到get时就调用如下代码去执行,同理这里也可以去写doPost.执行效果如下
image

servlet生命周期

1)服务器启动时 (web.xml 中配置 load-on-startup=1,默认为 0)或者第一次请求该 servlet 时,就会初始化一个 Servlet 对象,也就是会执行初始化方法 init(ServletConfig conf)。(这里在涉及servelt内存马时还会提及)

2)servlet 对象去处理所有客户端请求,在 service(ServletRequest req,ServletResponse res) 方法中执行

3)服务器关闭时,销毁这个 servlet 对象,执行 destroy() 方法。

4)由 JVM 进行垃圾回收。

Filter

filter 也称之为过滤器,是对 Servlet 技术的一个强补充,其主要功能是在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest ,根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据;在 HttpServletResponse 到达客户端之前,拦截 HttpServletResponse ,根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据。
它主要用来拦截客户端的请求数据,并对请求数据进行筛选、过滤,比如完成一些通用的操作,比如:判断登录是否成功、统一编码、权限控制、敏感字符处理。
工作原理如图所示
image
Filter 程序是一个实现了特殊接口的 Java 类,与 Servlet 类似,也是由 Servlet 容器进行调用和执行的。
demo

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
//拦截所有请求
public class FilterDemo1 implements Filter {
    /**
     * 初识化方法
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }
    /**
     * 过滤方法
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Hello Filter~~");

        //放行
     //   filterChain.doFilter(servletRequest,servletResponse);
        //如果不放行,浏览器将无法访问到hello.jsp
    }
    /**
     * 销毁方法
     */
    @Override
    public void destroy() {

    }
}

具体的测试就是,不过取消注释filterChain.doFilter(servletRequest,servletResponse);是无法正常访问的.因为上文说了其执行顺序为listener,filter,servlet.且同上@WebFilter("/*")并表示访问任意路径所有的请求都会经过该filter.且如果我们设置的不止于一个filter时就会产生一个filter链,会按照我们注册filter的顺序依次执行doFIlter.对于之前的filter其会执行doFilter()—-> internalDoFilter()—-> doFilter();直到最后一个 filter 被调用。最后一个 filter 会执行完 doFilter()操作,随后会跳转到 Servlet.service(),交给servlet处理.
当多个 Filter 同时存在的时候,组成了 Filter 链。Web 服务器根据 Filter 在 web.xml 文件中的注册顺序,决定先调用哪个 Filter。当第一个 Filter 的 doFilter 方法被调用时,web服务器会创建一个代表 Filter 链的 FilterChain 对象传递给该方法,通过判断 FilterChain 中是否还有 Filter 决定后面是否还调用 Filter。
过滤器链就是当我们使用浏览器访问一个资源时,中间被多个(至少两个)Filter进行了拦截,这多个过滤器就组成了过滤器链。
例如,以下的Filter1和Filter2就形成了过滤器链:
image
后续的更多的会在filter内存马中提及.顺带一提,个人理解对于常见的Java安全问题,如反序列化,fastjson,还有这里其危险的地方都在于方法的自动执行.反序列化的readobject,fastjson的settergetter,这里就是doFilter.明显我们期望就是我们自己写个filter,且设置过滤路径为/*,然后在doFilter中写入危险代码.那么我们在访问任意路径时都会造成危险代码的执行.

生命周期

与 servlet 一样,Filter 的创建和销毁也由 Web 容器负责。Web 应用程序启动时,Web 服务器将创建 Filter 的实例对象,并调用其 init() 方法,读取 web.xml 配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter 对象只会创建一次,init 方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。 Filter 对象创建后会驻留在内存,当 Web 应用移除或服务器停止时才销毁。在 Web 容器卸载 Filter 对象之前被调用。该方法在 Filter 的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

后续我们看调试就知道了,这样讲太空洞,个人理解:先去 web.xml 里面找接口 —> init()—> 执行 doFilter()—> destory()

Listener

简介

Java Web 开发中的监听器(Listener)就是 Application、Session 和 Request 三大对象创建、销毁或者往其中添加、修改、删除属性时自动执行代码的功能组件。

ServletContextListener:对Servlet上下文的创建和销毁进行监听; ServletContextAttributeListener:监听 Servlet 上下文属性的添加、删除和替换;

HttpSessionListener:对 Session 的创建和销毁进行监听。Session 的销毁有两种情况,一个中 Session 超时,还有一种是通过调用 Session 对象的 invalidate() 方法使 session 失效。

HttpSessionAttributeListener:对 Session 对象中属性的添加、删除和替换进行监听;

ServletRequestListener:对请求对象的初始化和销毁进行监听; ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听。
demo

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import java.util.EventListener;

@WebListener("/listenerTest")
public class ListenerTest implements ServletRequestListener {

    public ListenerTest(){
    }

    @Override
 public void requestDestroyed(ServletRequestEvent sre) {

    }

    @Override
 public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("Listener 被调用");
 }
}

web.xml写入

<listener>
 <listener-class>org.example.ma.ListenerTest</listener-class>
</listener>

然后在控制台可以看到
image

顺带一提上文提及绑定url方式也可以在web.xml设置

<servlet>
        <servlet-name>HelloServlet</servlet-name>//类名
        <servlet-class>com.demo.servlet.HelloServlet</servlet-class>//类所在位置
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>//类名
        <url-pattern>/hello</url-pattern>//url映射
    </servlet-mapping>
 <filter> <filter-name>filter</filter-name>//同上
 <filter-class>filter</filter-class>
 </filter>
 <filter-mapping> <filter-name>filter</filter-name>
 <url-pattern>/filter</url-pattern>
     <listener>
 <listener-class>org.example.ma.ListenerTest</listener-class>
</listener>

Tomcat

什么是 Tomcat

大概可以通过对标 Apache 来看一看。

Apache 是 Web 服务器(静态解析,如 HTML),Tomcat 是 java 应用服务器(动态解析,如 JSP)

Tomcat 只是一个 servlet (jsp 也翻译成 servlet)容器,可以认为是 Apache 的扩展,但是可以独立于 Apache 运行。

  • 一句话概括一下,就是 Web 服务器,比较不稳定,但是业务能力比较强。

我们根据上面的基础知识可以知道 Tomcat 是 Web 应用服务器,是一个 Servlet/JSP 容器,而 Servlet 容器从上到下分别是 Engine、Host、Context、Wrapper。
第一层---server组件 (它在tomcat的最外层,所以可以将一个server实例看成一个tomcat

server作用:掌控全局,管理各个部分之间的工作

全局管理:Server组件是整个Tomcat实例的顶级容器,负责管理和协调所有Service组件(由上面的图我们可以看出server位于tomcat的最外围,包含着service、connector、engine、host等一系列容器)。它提供了服务器级别的配置,包括定义全局服务器配置、管理服务生命周期(tomcat从启动到停止)等。
监听关闭命令:Server组件会监听某个特定端口(默认是8005),以接收SHUTDOWN命令来关闭Tomcat服务器。当需要关闭服务器时,可以通过向该端口发送SHUTDOWN命令来实现。
提供监听器机制:Server组件提供了监听器机制,用于在Tomcat整个生命周期中对不同事件进行处理。这些监听器可以执行诸如初始化APR库、初始化Jasper组件、防止JRE内存泄露等任务。

第二层---service组件

Service组件在Tomcat中的主要作用是管理一组关联的Connector和Engine组件。它负责接收和处理客户端请求,以及将这些请求传递给Engine组件进行进一步的处理。简单来说,Service组件是Tomcat中对外提供服务的核心组件。

深入讲解: Service主要用于关联一个引擎和与此引擎相关的连接器,每个连接器通过一个特定的端口和协议接收请求并将其转发至关联的引擎进行处理。

如上图中的红色文字:这个web服务器就是用来接收请求,但是它不能处理请求,它要将请求转发给下一个部件,这个所谓的下一个部件就是engine这个组件,也就是引擎,这个web服务器就是连接器,而service就是工作在web服务器和engine这个组件连接途径上的,所以说“Service主要用于关联一个引擎和与此引擎相关的连接器”

接收请求:当客户端向Tomcat服务器发送请求时,这些请求首先会被Connector组件(很明显,这个connector组件包含在上图web服务器中)接收。
封装请求:Connector组件将接收到的请求封装成Request和Response对象。
传递请求:封装好的Request对象会被传递给Engine组件进行处理。
处理请求:Engine组件根据请求的Host和Context查找对应的Web应用,并调用相应的Servlet来处理请求。
生成响应:处理完请求后,Engine组件会生成相应的Response对象,并将其返回给Connector组件。
发送响应:Connector组件将Response对象发送给客户端,完成整个请求处理流程。

第三层---Engine组件(Tomcat中的Engine组件是其核心组件之一,负责处理来自客户端的请求,并将这些请求分发到对应的虚拟主机(Host)或Web应用程序(Context)进行处理。)

简而言之,就是客户端发送请求,connector接收后把请求变成tomcat内部各个组件能看懂的信息,然后将其传给Engine,Engine再根据这个信息(请求的样子)将其传给对应的host,host再根据这个信息(请求的样子)将其传给对应的context,context根据信息,让servlet来处理信息,然后servlet将处理的结果传给客户端。这就像把一个皮球踢来踢去!

第四层---Host组件
image
第五层---Context组件

管理Servlet实例:Context组件负责管理和维护Servlet实例的生命周期,包括Servlet的装载、初始化、执行和资源回收等。
提供Web应用环境:Context组件为Web应用提供了运行所需的环境和资源,包括ClassLoader、资源访问对象等。
处理HTTP请求:当Connector组件接收到HTTP请求后,会通过匹配请求URI的上下文路径来选择相应的Context来处理该请求。然后,Context会根据web.xml文件中定义的servlet映射来选择一个正确的Servlet来处理该请求。
第六层 --- wrapper组件

扮演着管理Servlet实例的重要角色,Wrapper组件是Tomcat中最底层的容器,它直接包装了java.servlet.Servlet实例。每个Wrapper组件都对应一个特定的Servlet,并负责该Servlet的加载、初始化、执行以及资源回收等生命周期管理。

小结

只能说tomcat的内部时非常的复杂.这里谈及是因为在跟进到后续的内存马学习中,我们自己写入像filter这些时会跟进到他tomcat的这些组件代码中来进一步帮助理解其产生过

参考文献

https://drun1baby.top/2022/08/22/Servlet-项目搭建/
https://drun1baby.top/2022/08/21/Java内存马系列-02-内存马介绍/
https://drun1baby.top/2022/08/19/Java内存马系列-01-基础内容学习/
https://www.cnblogs.com/jadite/p/16951328.html

文章来源: https://www.freebuf.com/articles/web/458950.html
如有侵权请联系:admin#unsafe.sh