技术分享|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⼯具类
结果演示访问查看效果