技术分享|Tomcat内存马
发布时间:
2024-03-01 14:21

01 Tomcat Container容器
Engine:Catalina Servlet引擎,用来管理多个Host。
Host :—个Host代表—个虚拟主机,可以包含多个 Context。
Context:一个Context代表一个web应用,可以包含多个
Wrapper:—个Wrapper代表—个Servlet,Wrapper负责管理Servlet包括Servlet的装载、初始化、执行以及资源回收。默认实现为StandardEngine、StandardHost、StandardContext,StandardWrapper。
02 JavaWeb组件
1、Servlet
接受请求参数、处理请求,响应结果。生命周期:
voidinit(ServletConfig):初始化
void destroy():销毁
void Service(ServletRequest request,ServletResponse response):处理请求
2、Filter
过滤器,在请求到达目标资源之前进行拦截、响应到达浏览器之前预处理。由filterChain链式调用其doFilter()方法,按照顺序执行。
3、Listener
监听器,用于监听web应用程序中的ServletContext、HttpSession和ServletRequest这三大域对象的创建、销毁事件以及监听这些域对象中的属性发生修改的事件。
03 Tomcat pipeline和valve
1、pipeline
Tomcat使用管道模式(Pipeline)处理HTTP请求。该模式将请求交给多个Valve进行处理,并由每个Valve按照特定顺序执行处理逻辑。Pipeline有一个标准实现StandardPipeline。
2、valve
Valve是Tomcat中用于处理HTTP请求的组件。每个Valve都负责处理HTTP请求中的一个步骤,并将处理后的请求传递给下一个Valve。Valve不同容器有不同的实现,如StandardWrapper的StandardWrapperValve。
04 Tomcat Context
在后续文章中添加Servlet、Filter、Listener、Valve均需要获取到StandardContext对象。因此需要先了解StandardContext对象的获取方式。
1、request
Tomcat中Web应用中request.getSession().getServletContext获取的是ApplicationContextFacade对象。该对象对ApplicationContext进行了封装,而ApplicationContext实例中又包含了StandardContext 实例,所以当request存在的时候我们可以通过反射来获取StandardContext对象

Servlet环境的request实际上为RequestFacade对象,request属性存储Request对象,Request对象的getContext可以直接拿到Context。

2、类加载器
从Thread.currentThread().getContextClassLoader()中获取StandardContext。
3、JMX
Tomcat的MBean服务器提供了对所有Tomcat内部组件的访问,包括StandardContext。
05 Tomcat 调试
1、服务加载
在ContextConfig下打断点,启动Tomcat服务

查看部分堆栈信息

configureContext载入Web.xml配置

addFilterDef添加FilterDef

addFilterMap添加FilterMap

获取Listener配置信息,添加Listener

addApplicationListener添加listener

获取Servlets配置信息,添加Servlet

createWrapper添加Servlet

服务启动时,⾸先会通过Pipeline添加Valve配置

总结服务启动过程:
(1)Pipeline通过addValve添加Valva
(2)获取Web.xml配置信息
(3)获取Filter配置,添加FilterDef和FilterMap
(4)获取Listener配置信息,addApplicationListener添加listener
(5)获取Servlets配置信息,createWrapper添加Servlet
2、服务加载
在测试服务的doGet打断点

查看部分堆栈信息

3、Valve调用
查看Valve调用情况,按照Engine、Host、Context、Wrapper依次调用Valve的invoke方法StandardEngineValve

StandardHostValve

StandardContextValve

StandardWrapperValve

4、Servlet调用
StandardHostValve处理Listener

StandardContextValue.invoke获取Wrapper

StandardWrapperValue.invoke处理doFilter

调⽤HttpServlet.service⽅法

HttpServlet.service提供了多种请求⽅式

最后进⼊doGET⽅法

5、Filter调⽤
ApplicationFilterFactory创建FilterChain

查看createFilterChain⽅法,从Standardcontext获取filterMaps

遍历filterMap匹配url调⽤addFilter添加到filterChain

获取filterChain后调⽤filterChain.doFilter⽅法

查看doFilter⽅法,调⽤internalDoFilter循环chain依次调⽤各filter的doFilter⽅法,但internalDoFilter循环调⽤的并不是FilterDef和FilterMaps,⽽是filterConfig

调⽤结束后返回到service

6、Listener调⽤
在Host中对Request请求创建监听器进⾏检查

fireRequestInitEvent调⽤get⽅法获取全部监听器,调⽤requestInitialized⽅法

查看requestInitialized⽅法

Request请求销毁

调⽤requestDestroyed⽅法

06 Servlet
1、Servlet注册
查看Servlet注册完整过程首先通过context.createWrapper创建Wrapper,设置启动顺序、名称、类名。

调⽤addChild⽅法将wrapper添加到StandardContext,调⽤addServletMapppingDecoded添加映射

总结Servlet注册过程:
(1)StandardContext.createWrapper创建wrapper
(2)wrapper.setLoadOnStartup设置启动顺序
(3)wrapper.setName设置SerletName
(4)wrapper.setServletClass设置SerletClass
(5)context.addChild添加wrapper
(6)context.addServletMapppingDecoded添加映射
2、Servlet
示例定义内部类实现Servlet接口,重写Service方法

获取context创建wrapper,设置Servlet属性,添加wrapper和映射

访问⻚⾯注册Servlet

查看注册结果

3、Servlet
销毁获取context,使用removeChild和removeServletMapping删除对应的Servlet和映射

查看销毁结果

07 Filter
1、Filter注册
查看Filter注册完整过程,创建FilterDef,调用context.addFilterDef添加FilterDef

查看addFilterDef调⽤context.filterDefs.put写⼊FilterName和FilterDef

调⽤context.addFilterMap添加FilterMap

查看addFilterMap,调⽤filterMap.add添加filterMap

由于前⾯doFilter使⽤的是filterConfigs,查看context的filterStart⽅法,遍历filterDefs,将value封装为ApplicationFilterConfig对象放⼊filterConfigs变量

总结Filter注册过程:
(1)创建filterDef,设置setFilter、setFilterName、setFilterClass
(2)context.addFilterDef添加FilterDef
(3)创建filterMap,设置addURLPattern、setFilterName、setDispatcher
(4)context.addFilterMap添加filterMap
(5)创建ApplicationFilterConfig实例
(6)filterConfigs.put添加config
2、Filter示例
定义内部类实现Filter接口

按照注册过程,创建并添加filterDef、filterMap,然后创建ApplicationFilterConfig实例,添加config

注册Filter

查看注册结果

3、Filter销毁
调用context.findFilterDefs获取全部Filter定义,通过context.removeFilterDef删除指定FilterDef,调用context.findFilterMaps获取全部Filter映射,通过context.removeFilterMap删除指定映射。

查看销毁结果

08 Listener
1、Listener注册
查看Listener注册过程,调用context.addApplicationListene添加listener

查看addApplicationListene实现

总结Listener注册过程:
(1)创建Listener
(2)context.addApplicationListene添加listener
2、Listener示例
定义内部类,实现ServletRequestListener接口

通过context.addApplicationListene添加listener

注册listener

查看注册结果

3、Listener销毁
调用context.getApplicationEventListeners获取全部监听器,判断监听器是否为注册添加,不是则添加 到newListeners列表,调用context.setApplicationEventListeners设置新监听器。

查看销毁结果

09 Valve
1、Valve注册
查看Valve注册过程通过pipeline.addValve添加valve

查看addValve实现

总结Valve注册过程:
(1)创建Valve
(2)context.addValve添加Valve
2、Valve示例
定义内部类继承ValveBase

调⽤context.addValve添加Valve

注册Valve

查看注册结果

3、Valve销毁
调用gitPipeline和getValves获取全部Valve,通过removeValve删除Valve

查看销毁结果

10 内存马
1、内存马
开发—个蚁剑Webshell工具类,方便内存马实现

2、Servlet内存⻢
在service⽅法中调⽤Webshell⼯具类

3、Filter内存⻢
在doFilter⽅法中调⽤Webshell⼯具类

4、Listener内存⻢
在requestInitialized⽅法中调⽤Webshell⼯具类

5、Valve内存⻢
在invoke⽅法中调⽤Webshell⼯具类

结果演示访问查看效果







