Tomcat|Tomcat 内存马(一)Listener型
一、Tomcat介绍
Tomcat的主要功能
tomcat作为一个 Web 服务器,实现了两个非常核心的功能:
- Http 服务器功能:进行 Socket 通信(基于 TCP/IP),解析 HTTP 报文
- Servlet 容器功能:加载和管理 Servlet,由 Servlet 具体负责处理 Request 请求
文章图片
以上两个功能,分别对应着tomcat的两个核心组件连接器(Connector)和容器(Container),连接器负责对外交流(完成 Http 服务器功能),容器负责内部处理(完成 Servlet 容器功能)。
文章图片
- Server
Server 服务器的意思,代表整个 tomcat 服务器,一个 tomcat 只有一个 Server Server 中包含至少一个 Service 组件,用于提供具体服务。
- Service
服务是 Server 内部的组件,一个Server可以包括多个Service。它将若干个 Connector 组件绑定到一个 Container
- Connector
称作连接器,是 Service 的核心组件之一,一个 Service 可以有多个 Connector,主要连接客户端请求,用于接受请求并将请求封装成 Request 和 Response,然后交给 Container 进 行处理,Container 处理完之后在交给 Connector 返回给客户端。
- Container
负责处理用户的 servlet 请求
连接器主要完成以下三个核心功能:
- socket 通信,也就是网络编程
- 解析处理应用层协议,封装成一个 Request 对象
- 将 Request 转换为 ServletRequest,将 Response 转换为 ServletResponse
文章图片
Container容器
Container组件又称作Catalina,其是Tomcat的核心。在Container中,有4种容器,分别是Engine、Host、Context、Wrapper。这四种容器成套娃式的分层结构设计。
文章图片
四种容器的作用:
- Engine
表示整个 Catalina 的 Servlet 引擎,用来管理多个虚拟站点,一个 Service 最多只能有一个 Engine,但是一个引擎可包含多个 Host - Host
代表一个虚拟主机,或者说一个站点,可以给 Tomcat 配置多个虚拟主机地址,而一个虚拟主机下可包含多个 Context - Context
表示一个 Web 应用程序,每一个Context都有唯一的path,一个Web应用可包含多个 Wrapper - Wrapper
表示一个Servlet,负责管理整个 Servlet 的生命周期,包括装载、初始化、资源回收等
文章图片
tomcat的结构图:
文章图片
二、Listener内存马 请求网站的时候, 程序先执行listener监听器的内容:Listener -> Filter -> Servlet
文章图片
Listener是最先被加载的, 所以可以利用动态注册恶意的Listener内存马。而Listener分为以下几种:
- ServletContext,服务器启动和终止时触发
- Session,有关Session操作时触发
- Request,访问服务时触发
ServletRequestListener接口
如果在Tomcat要引入listener,需要实现两种接口,分别是
LifecycleListener
和原生EvenListener
。实现了
LifecycleListener
接口的监听器一般作用于tomcat初始化启动阶段,此时客户端的请求还没进入解析阶段,不适合用于内存马。所以来看另一个
EventListener
接口,在Tomcat中,自定义了很多继承于EventListener
的接口,应用于各个对象的监听。文章图片
重点来看
ServletRequestListener
接口文章图片
ServletRequestListener
用于监听ServletRequest
对象的创建和销毁,当我们访问任意资源,无论是servlet、jsp还是静态资源,都会触发requestInitialized
方法。在这里,通过一个demo来介绍下
ServletRequestListener
与其执行流程配置tomcat源码调试环境:https://zhuanlan.zhihu.com/p/35454131
【Tomcat|Tomcat 内存马(一)Listener型】写一个继承于
ServletRequestListener
接口的TestListener
:public class TestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("执行了TestListener requestDestroyed");
}@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("执行了TestListener requestInitialized");
}
}
在web.xml中配置:
test.TestListener
访问任意的路径:http://127.0.0.1:8080/11
文章图片
可以看到控制台打印了信息,tomcat先执行了
requestInitialized
,然后再执行了requestDestroyed
文章图片
requestInitialized:在request对象创建时触发
requestDestroyed:在request对象销毁时触发
StandardContext对象
StandardContext
对象就是用来add恶意listener的地方接以上环境,直接在
requestInitialized
处下断点,访问url后,显示出整个调用链文章图片
通过调用链发现,Tomcat在
StandardHostValve
中调用了我们定义的Listener文章图片
跟进
context.fireRequestInitEvent
,在如图红框处调用了requestInitialized
方法文章图片
往上追踪后发现,以上的listener是在
StandardContext#getApplicationEventListeners
方法中获得的文章图片
文章图片
在
StandardContext#addApplicationEventListener
添加了listener文章图片
这时候我们思路是,调用
StandardContext#addApplicationEventListener
方法,add我们自己写的恶意listener在jsp中如何获得
StandardContext
对象方式一:
方式二:
WebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase) Thread.currentThread().getContextClassLoader();
StandardContext standardContext = (StandardContext) webappClassLoaderBase.getResources().getContext();
以下是网络上公开的内存马:
test.jsp
首先访问上传的test.jsp生成listener内存马,之后即使test.jsp删除,只要不重启服务器,内存马就能存在。
文章图片
文章图片
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 读司马懿,知人间事,品百味人生
- Linux下面如何查看tomcat已经使用多少线程
- 心安理得的心猿意马
- 探索免费开源服务器tomcat的魅力
- 17.8.21
- 推广大师(黄马可短篇小说精选|推广大师(黄马可短篇小说精选 x5)
- 快意恩仇
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- 演讲手势