Tomcat|Tomcat 内存马(二)Filter型

一、Tomcat处理请求 在前一个章节讲到,tomcat在处理请求时候,首先会经过连接器Coyote把request对象转换成ServletRequest后,传递给Catalina进行处理。
Tomcat|Tomcat 内存马(二)Filter型
文章图片
在Catalina中有四个关键的容器,分别为Engine、Host、Context、Wrapper。这四种容器成套娃式的分层结构设计。
Tomcat|Tomcat 内存马(二)Filter型
文章图片
接下来我们知道当tomcat接收到请求时候,依次会经过Listener -> Filter -> Servlet
Tomcat|Tomcat 内存马(二)Filter型
文章图片

其实我们也可以通过动态添加Filter来构成内存马,不过在此之前先了解下tomcat处理请求的逻辑
Tomcat|Tomcat 内存马(二)Filter型
文章图片

从上图中可以看到,请求到达Wrapper容器时候,会开始调用FilterChain,这个FilterChain就是若干个Filter组成的过滤器链。最后才会达到Servlet。只要把我们的恶意filter放入filterchain的第一个位置,就可以触发恶意filter中的方法。
二、Filter注册流程 要在FilterChain中加入恶意filter,首先要了解tomcat中Filter的注册流程
Tomcat|Tomcat 内存马(二)Filter型
文章图片

在上图中可以看到,Wrapper容器调用FilterChain的地方就在StandardWrapperValve类中
Tomcat|Tomcat 内存马(二)Filter型
文章图片

调试
注册一个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型
文章图片

查看调用链
Tomcat|Tomcat 内存马(二)Filter型
文章图片
可以看到在StandardWrapperValve#invoke中,通过createFilterChain方法获得了一个ApplicationFilterChain类型的filterChain
Tomcat|Tomcat 内存马(二)Filter型
文章图片

其filterChain中存放了两个ApplicationFilterConfig类型的filter,其中第一个就是TestFilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

然后在下面196行调用了ApplicationFilterChain#doFilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

跟进doFilter方法,在方法中调用了internalDoFilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

跟进internalDoFilter后看到,从filters数组里面拿到了第一个filter即Testfilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

最后调用了filter.doFilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

Tomcat|Tomcat 内存马(二)Filter型
文章图片

可以看到,filter是从filters数组中拿到的,看看filters数组是什么,Ctrl+左击
Tomcat|Tomcat 内存马(二)Filter型
文章图片

其实就是一个ApplicationFilterConfig类型的对象数组,它的值也就是前面的说的通过createFilterChain方法获得的
Tomcat|Tomcat 内存马(二)Filter型
文章图片

Tomcat|Tomcat 内存马(二)Filter型
文章图片

接下来查看createFilterChain如何把我们写的TestFilter添加ApplicationFilterConfig
跟进ApplicationFilterFactory#createFilterChain中,看到首先64行拿到了个ServletRequest,然后通过ServletRequest#getFilterChain获取到了filterChain
Tomcat|Tomcat 内存马(二)Filter型
文章图片

继续往下看,通过StandardContext对象找到了filterMaps[]
Tomcat|Tomcat 内存马(二)Filter型
文章图片

然后又通过filterMaps中的名字,找到StandardContext对象中的FilterConfig,最后把FilterConfig加入了filterChain中
Tomcat|Tomcat 内存马(二)Filter型
文章图片

跟进filterChain.addFilter看到,也就是加入了前面说的filters数组ApplicationFilterConfig中。这里和上面一步的操作就是遍历filter放入ApplicationFilterConfig
Tomcat|Tomcat 内存马(二)Filter型
文章图片

通过调试发现,有两个很重要的变量,filterMap和filterConfig
  • filterMaps拿名字
  • filterConfigs拿过滤器
其实这两个变量都是在StandardContext对象里面存放了,其中还有个变量filterDefs也是重要的变量
Tomcat|Tomcat 内存马(二)Filter型
文章图片

Tomcat|Tomcat 内存马(二)Filter型
文章图片

分析filterMaps、filterConfigs、filterDefs
1)filterMaps
既然这三个变量都是从StandardContext中获得,那么查看StandardContext发现有两个方法可以添加filterMap
Tomcat|Tomcat 内存马(二)Filter型
文章图片

Tomcat|Tomcat 内存马(二)Filter型
文章图片

2)filterConfigs
StandardContext中同样寻找添加filterConfig值的地方,发现有一处filterStart方法
Tomcat|Tomcat 内存马(二)Filter型
文章图片

此处添加是在tomcat启动时完成,所以下好断点启动tomcat
filterDefs中存放着TestFilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

遍历这个filterDefs,拿到key为TestFilter,value为FilterDef对象,值test.Testfilter
Tomcat|Tomcat 内存马(二)Filter型
文章图片

接下来new了一个ApplicationFilterConfig,放入了value
Tomcat|Tomcat 内存马(二)Filter型
文章图片

然后把nam=TestFilter和filterConfig放入了filterConfigs
Tomcat|Tomcat 内存马(二)Filter型
文章图片

3)filterDefs
以上的filterDefs才是真正放了过滤器的地方,那么我们看下filterDefs在哪里被加入了
StandardContext中同样有个addFilterDef方法
Tomcat|Tomcat 内存马(二)Filter型
文章图片

可以想到,tomcat是从web.xml中读取的filter,然后加入了filterMap和filterDef变量中,以下对应着这两个变量
Tomcat|Tomcat 内存马(二)Filter型
文章图片

内存马
我们通过控制filterMaps、filterConfigs、filterDefs的值,则可以注入恶意的filter
  • filterMaps:一个HashMap对象,包含过滤器名字和URL映射
  • filterDefs:一个HashMap对象,过滤器名字和过滤器实例的映射
  • filterConfigs变量:一个ApplicationFilterConfig对象,里面存放了filterDefs

访问:http://127.0.0.1:8080/testF.jsp显示注入成功
Tomcat|Tomcat 内存马(二)Filter型
文章图片

执行命令:http://127.0.0.1:8080/?cmd=cat /etc/issue
Tomcat|Tomcat 内存马(二)Filter型
文章图片

三、参考: http://wjlshare.com/archives/1529#0x04_Filter
http://li9hu.top/tomcat内存马一-初探/
【Tomcat|Tomcat 内存马(二)Filter型】https://www.cnblogs.com/nice0e3/p/14622879.html#0x03-内存马实现

    推荐阅读