Tomcat|Tomcat 内存马(二)Filter型
一、Tomcat处理请求
在前一个章节讲到,tomcat在处理请求时候,首先会经过连接器Coyote把request对象转换成ServletRequest后,传递给Catalina进行处理。
文章图片
在Catalina中有四个关键的容器,分别为Engine、Host、Context、Wrapper。这四种容器成套娃式的分层结构设计。
文章图片
接下来我们知道当tomcat接收到请求时候,依次会经过Listener -> Filter -> Servlet
文章图片
其实我们也可以通过动态添加Filter来构成内存马,不过在此之前先了解下tomcat处理请求的逻辑
文章图片
从上图中可以看到,请求到达Wrapper容器时候,会开始调用FilterChain,这个FilterChain就是若干个Filter组成的过滤器链。最后才会达到Servlet。只要把我们的恶意filter放入filterchain的第一个位置,就可以触发恶意filter中的方法。
二、Filter注册流程
要在FilterChain中加入恶意filter,首先要了解tomcat中Filter的注册流程
文章图片
在上图中可以看到,Wrapper容器调用FilterChain的地方就在StandardWrapperValve
类中
文章图片
调试
注册一个filter:
public class TestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter初始化");
}@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("doFilter过滤");
//放行
chain.doFilter(request,response);
}@Override
public void destroy() {
System.out.println("filter销毁");
}
}
配置web.xml
TestFilter
test.TestFilter
TestFilter
/*
在doFilter处下断点,访问任意url:http://127.0.0.1:8080/xxx
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/4bb2d3a27f5d4b449de54ffe28ee880e.jpg)
文章图片
查看调用链
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/c2b63eeed2244621986f6b8f34cd5183.jpg)
文章图片
可以看到在
StandardWrapperValve#invoke
中,通过createFilterChain
方法获得了一个ApplicationFilterChain
类型的filterChain![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/8725b0f891c545899a985cb6a516960c.jpg)
文章图片
其filterChain中存放了两个
ApplicationFilterConfig
类型的filter,其中第一个就是TestFilter![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/b3397c54c46846eeaaf08be5f1577f23.jpg)
文章图片
然后在下面196行调用了
ApplicationFilterChain#doFilter
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/069048f14af3456a8e2d95dd80b44344.jpg)
文章图片
跟进
doFilter
方法,在方法中调用了internalDoFilter
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/993fd3868d8d47a7b94977e4f24febcc.jpg)
文章图片
跟进
internalDoFilter
后看到,从filters数组里面拿到了第一个filter即Testfilter
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/c2073401db904f188b271e1fed915149.jpg)
文章图片
最后调用了
filter.doFilter
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/9b5cbae5af0c4d9d8b8161174b1dca7d.jpg)
文章图片
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/1d4ce28295d94b049552e0d65b0c448f.jpg)
文章图片
可以看到,filter是从filters数组中拿到的,看看filters数组是什么,Ctrl+左击
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/2637f3ea5bbb4379b9b6981475654d3c.jpg)
文章图片
其实就是一个
ApplicationFilterConfig
类型的对象数组,它的值也就是前面的说的通过createFilterChain
方法获得的![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/8725b0f891c545899a985cb6a516960c.jpg)
文章图片
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/b3397c54c46846eeaaf08be5f1577f23.jpg)
文章图片
接下来查看
createFilterChain
如何把我们写的TestFilter添加ApplicationFilterConfig
的跟进
ApplicationFilterFactory#createFilterChain
中,看到首先64行拿到了个ServletRequest
,然后通过ServletRequest#getFilterChain
获取到了filterChain![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/2deec3abc84f4c0a8699c278dd817a75.jpg)
文章图片
继续往下看,通过
StandardContext
对象找到了filterMaps[]![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/0ad93934cee04ed3bd8ef1c9aae21809.jpg)
文章图片
然后又通过filterMaps中的名字,找到
StandardContext
对象中的FilterConfig,最后把FilterConfig加入了filterChain中![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/6b44ff6af40d4aef81af2ffc0725a828.jpg)
文章图片
跟进
filterChain.addFilter
看到,也就是加入了前面说的filters数组ApplicationFilterConfig
中。这里和上面一步的操作就是遍历filter放入ApplicationFilterConfig
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/ec73f9d14d83429fa4c1b2042336da09.jpg)
文章图片
通过调试发现,有两个很重要的变量,filterMap和filterConfig
- filterMaps拿名字
- filterConfigs拿过滤器
StandardContext
对象里面存放了,其中还有个变量filterDefs也是重要的变量![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/0ad93934cee04ed3bd8ef1c9aae21809.jpg)
文章图片
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/8396e17a42354e54a59a95980effb983.jpg)
文章图片
分析filterMaps、filterConfigs、filterDefs
1)filterMaps
既然这三个变量都是从
StandardContext
中获得,那么查看StandardContext
发现有两个方法可以添加filterMap![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/8e3091e6b2844234bec76de2eb15de89.jpg)
文章图片
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/598c1b81e9674d409d3dc4cdffa39b9d.jpg)
文章图片
2)filterConfigs
在
StandardContext
中同样寻找添加filterConfig值的地方,发现有一处filterStart
方法![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/5e96ff8be5774a14bcc8850347887e15.jpg)
文章图片
此处添加是在tomcat启动时完成,所以下好断点启动tomcat
filterDefs
中存放着TestFilter![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/30e73999a3a4420587cccaaa235f6f7c.jpg)
文章图片
遍历这个
filterDefs
,拿到key为TestFilter,value为FilterDef对象,值test.Testfilter![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/64f17353a1cc4d21ba4403406048acdf.jpg)
文章图片
接下来new了一个
ApplicationFilterConfig
,放入了value![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/b367a6cd959842269104bdb952e65087.jpg)
文章图片
然后把nam=TestFilter和filterConfig放入了filterConfigs
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/23f4828f9e4b4ae3bc361958262505af.jpg)
文章图片
3)filterDefs
以上的filterDefs才是真正放了过滤器的地方,那么我们看下filterDefs在哪里被加入了
在
StandardContext
中同样有个addFilterDef
方法![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/5dea9978622047e7b8b5a04071216262.jpg)
文章图片
可以想到,tomcat是从web.xml中读取的filter,然后加入了filterMap和filterDef变量中,以下对应着这两个变量
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/9c222af533e34008924761ab1c4da1eb.jpg)
文章图片
内存马
我们通过控制filterMaps、filterConfigs、filterDefs的值,则可以注入恶意的filter
- filterMaps:一个HashMap对象,包含过滤器名字和URL映射
- filterDefs:一个HashMap对象,过滤器名字和过滤器实例的映射
- filterConfigs变量:一个ApplicationFilterConfig对象,里面存放了filterDefs
访问:http://127.0.0.1:8080/testF.jsp显示注入成功
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/a58185dd58b44d609eca1046bcd554b1.jpg)
文章图片
执行命令:http://127.0.0.1:8080/?cmd=cat /etc/issue
![Tomcat|Tomcat 内存马(二)Filter型](https://img.it610.com/image/info8/2404a367e9694b738603e4c46f7d13d7.jpg)
文章图片
三、参考: http://wjlshare.com/archives/1529#0x04_Filter
http://li9hu.top/tomcat内存马一-初探/
【Tomcat|Tomcat 内存马(二)Filter型】https://www.cnblogs.com/nice0e3/p/14622879.html#0x03-内存马实现
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 读司马懿,知人间事,品百味人生
- Linux下面如何查看tomcat已经使用多少线程
- 心安理得的心猿意马
- 探索免费开源服务器tomcat的魅力
- 17.8.21
- 推广大师(黄马可短篇小说精选|推广大师(黄马可短篇小说精选 x5)
- 快意恩仇
- Java内存泄漏分析系列之二(jstack生成的Thread|Java内存泄漏分析系列之二:jstack生成的Thread Dump日志结构解析)
- 演讲手势