Java内存马Tomcat篇01-Tomcat基础

0x00 前言

最近内存马技术如火如荼,频繁利用于攻防渗透领域。

本文就先学习一下Tomcat的基础架构和运行逻辑,为之后Tomcat的几种内存马打下基础。

0x01 Java Web 三大件

在讲Tomcat之前,先讲解一下 Java Web 三大件:Servlet,Filter,Listener。

当Tomcat收到请求后,请求会依次通过 Listener -> Filter -> Servlet。

Servlet

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

Servlet工作流程

  1. 客户端发起一个http请求(以GET类型为例)

  2. Servlet容器收到该请求,并根据该请求的信息,将其封装成HttpServletRequest和HttpServletResponse 对象

  3. Servlet容器调用HttpServlet的init()方法,该方法只在第一次请求被调用

  4. Servlet容器调用service()方法,该方法根据请求类型调用相应的方法,这里是调用doGet方法

  5. 业务逻辑处理完成之后,将结果返回给Servlet容器,然后容器将结果返回给客户端

  6. 容器关闭时,会调用destory方法

  7. 最后由JVM进行垃圾回收

根据上面的流程,不难理解Servlet接口所定义的几种方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package jakarta.servlet;

import java.io.IOException;

public interface Servlet {
void init(ServletConfig var1) throws ServletException;

ServletConfig getServletConfig();

void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

String getServletInfo();

void destroy();
}

Servlet生命周期

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

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

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

4)由JVM进行垃圾回收。

多提一嘴,Servelt会处理jsp文件,那么如果上传恶意的jsp小马,就可以拉Java内存马这头大马,俗称“小马拉大马”。

Filter

filter 也称之为过滤器,是对 Servlet 技术的一个强补充,其主要功能是在 HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest ,根据需要检查 HttpServletRequest,也可以修改 HttpServletRequest 头和数据;在 HttpServletResponse 到达客户端之前,拦截 HttpServletResponse ,根据需要检查 HttpServletResponse,也可以修改 HttpServletResponse 头和数据。

Filter程序是一个实现了特殊接口的Java类,与Servlet类似,也是由Servlet容器进行调用和执行的。

Filter工作流程

image-20250428183747139

image-20250428190739123

filter链:当多个filter同时存在的时候,组成了filter链。web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter。当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法,通过判断FilterChain中是否还有filter决定后面是否还调用filter。

  1. 在web.xml注册一个Filter来对某个Servelt程序进行拦截处理,该Filter可以决定是否将请求继续传递给Servlet程序,以及对请求和响应消息是否进行修改
  2. 当Servelt容器开始调用某个Servelt程序时,如果发现已经注册了一个拦截该Servelt的Filter,那么Servelt容器不再调用Servelt的service方法,而是调用Filter的doFilter方法,再由该方法判断是否激活service方法。
  3. 但在Filter.doFilter方法中不能直接调用Servlet的service方法,而是调用FilterChain.doFilter方法来激活目标 Servlet的service方法,FilterChain对象是通过Filter.doFilter方法的参数传递进来的。
  4. 在Filter.doFilter方法中调用FilterChain.doFilter方法的语句前后增加某些程序代码,就可以在Servlet进行响应前后实现某些特殊功能。
  5. 如果在Filter.doFilter方法中没有调用FilterChain.doFilter方法,则目标Servlet的service方法不会被执行,这样通过Filter就可以阻止某些非法的访问请求。

Filter的生命周期

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

Listener

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

  • ServletContextListener:对Servlet上下文的创建和销毁进行监听
  • ServletContextAttributeListener:监听Servlet上下文属性的添加、删除和替换
  • HttpSessionListener:对Session的创建和销毁进行监听。Session的销毁有两种情况,一个中Session超时,还有一种是通过调用 Session 对象的 invalidate() 方法使 session 失效
  • HttpSessionAttributeListener:对 Session 对象中属性的添加、删除和替换进行监听
  • ServletRequestListener:对请求对象的初始化和销毁进行监听;
  • ServletRequestAttributeListener:对请求对象属性的添加、删除和替换进行监听

用途:

可以使用监听器监听客户端的请求、服务端的操作等。通过监听器,可以自动出发一些动作,比如监听在线的用户数量,统计网站访问量、网站访问监控等。

这里也有插入内存马的思路,如果我们写了一个filter插在FilterChain的最前面,那么恶意的filter就会最先执行。

0x02 Tomcat

Tomcat概述

Tomcat是什么

Tomcat是java应用服务器(动态解析,如 JSP),也是Web服务器,比较不稳定,但是业务能力比较强。

Tomcat主要功能

tomcat作为一个 Web 服务器,实现了两个非常核心的功能:

  • Http 服务器功能:进行 Socket 通信(基于 TCP/IP),解析 HTTP 报文
  • Servlet 容器功能:加载和管理 Servlet,由 Servlet 具体负责处理 Request 请求

image-20250428194849085

Tomcat中实现Http服务器功能的是连接器(Connector),实现Servlet容器功能的是容器(Container)。

image-20250428195027615

  • Server
    Server代表整个tomcat服务器,一个Tomcat只有一个Server 。Server中包含至少一个Service组件,用于提供具体服务。

  • Service
    Service是Server内部的组件,一个Server可以包括多个Service。它将若干个Connector组件绑定到一个Container

  • Connector

    连接器,是Service的核心组件之一,一个Service可以有多个Connector,主要连接客户端请求,用于接受请求并将请求封装成Request 和Response,然后交给Container进行处理,Container处理完之后再交给Connector返回给客户端。

  • Container
    负责处理用户的 servlet 请求

Connector连接器

连接器主要完成以下三个核心功能:

  • socket通信,也就是网络编程
  • 解析处理应用层协议,封装成一个Request对象
  • 将Request转换为ServletRequest,将Response转换为ServletResponse

三个功能分别对应三个组件EndPoint、Processor、Adapter:

  • Endpoint 负责提供请求字节流给Processor
  • Processor 负责提供 Tomcat 定义的 Request 对象给 Adapter
  • Adapter 负责提供标准的 ServletRequest 对象给 Servlet 容器。

image-20250428195635121

Endpoint与Processor有一个组合名称为ProtocolHandler

Container容器

Container组件又称作Catalina,其是Tomcat的核心。在Container中,有4种容器,分别是Engine、Host、Context、Wrapper,这四种容器是父子关系。

image-20250428195854582

四种容器的作用:

  • Engine
    表示整个 Catalina 的 Servlet 引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine,但是一个引擎可包含多个 Host
  • Host
    代表一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可包含多个 Context
  • Context
    表示一个 Web 应用程序,每一个Context都有唯一的path,一个Web应用可包含多个 Wrapper
  • Wrapper
    表示一个Servlet,负责管理整个 Servlet 的生命周期,包括装载、初始化、资源回收等

如下图,a.com和b.com分别对应着两个Host:

image-20250428200036810

Tomcat的类加载机制

由于Tomcat中有多个WebApp,同时要确保之间相互隔离,所以 Tomcat 的类加载机制也不是传统的双亲委派机制。

每个WebApp用一个独有的ClassLoader实例来优先处理加载。它首先尝试自己加载某个类,如果找不到再交给父类加载器,其目的是优先加载WEB应用自己定义的类。

同时为了防止WEB应用自己的类覆盖JRE的核心类,在本地WEB应用目录下查找之前,先使用 ExtClassLoader(使用双亲委托机制)去加载,这样既打破了双亲委托,同时也能安全加载类。

0x03 Reference

JavaSec/5.内存马学习/Tomcat/Tomcat介绍/Tomcat介绍.md at main · Y4tacker/JavaSec

Java内存马系列-01-基础内容学习 | Drunkbaby’s Blog

擅长捉弄的内存马同学:Filter内存马(高甜) - FreeBuf网络安全行业门户