ServletListenerFilter内存马查杀手段一

admin 2023年6月24日01:52:16评论5 views字数 3874阅读12分54秒阅读模式
ServletListenerFilter内存马查杀手段一
Preface

之前的文章基本上都是围绕在tomcat或者spring环境下如何解决下面几个问题:

  1. 如何获取reqest / response域,也即是如何回显

  2. 如何利用这些中间件的特性进行内存马的构造,也即是动态创建路由

  3. 如何在反序列化漏洞的过程中注入内存马进行不出网等等的利用

总的来说,主要是从“攻”的角度进行内存马的学习。

接下来在继续抽空学习和挖掘其他的内存马的过程中,也开始从“防”的角度学习内存马的查杀。

前面几节主要是通过已知的一些查杀工具学习学习别人的思路。

Memshell-scanner

第一个学习的项目是c0ny1师傅在几年前开源的项目了

https://github.com/c0ny1/java-memshell-scanner

这个项目的主要思路是获取Tomcat下的所有的存在的Servlet/Filter/Listener

分别获取对应的各种信息,主要是通过判断对应的Servlet / Filter / Listener类是否在服务器端存在有对应的class文件,如果在classpath下没有对应的类文件则判断其可能为内存马

在这个tool中,内置了两个功能

  1. dump下对应的class文件

  2. kill掉对应的servlet / fitler / listener

接下来我们详细看看,是怎么进行判断的

Detection

Servlet

首先看看两个方法

getChildren

ServletListenerFilter内存马查杀手段一

这里方法的作用主要是通过从request这个HttpServletRequest对象中获取StandardContext类对象,这个类是"上下文接口的标准实现。每个子容器都必须是一个 Wrapper 实现,以处理指向特定 servlet 的请求。", 之后获取这个对象中的children属性,这个属性也是其父类ContainerBase的值

ServletListenerFilter内存马查杀手段一

也就是基于这个Context的一些子容器

也就是一些servlet -> StandardWrapper的映射

ServletListenerFilter内存马查杀手段一

而另一个方法getServletMaps

ServletListenerFilter内存马查杀手段一

类似的是从StandardContext对象中获取其属性servletMappings,也即是一些router -> servletName的映射

ServletListenerFilter内存马查杀手段一

之后的主要步骤也即是

ServletListenerFilter内存马查杀手段一

通过遍历存在的所有的所有路由

分别获取servletPath / servletName / standardWrapper这些信息之后

  1. 通过Class.forName进行类的加载

  2. 获取对应servlet类的classloader

  3. 通过对应的classloader调用getResource方法获取源文件

如果没有获取到文件就认为其可能为内存马

consideration

结合前面Tomcat Servlet的动态注册一个servlet的过程

Servlet存马的创建流程

  • 创建恶意Servlet

  • 用Wrapper对其进行封装

  • 添加封装后的恶意Wrapper到StandardContext的children当中

  • 添加ServletMapping将访问的URL和Servlet进行绑定

  1. 将恶意Servlet的Wrapper添加进入了children属性中

  2. 将路由的映射添加进入了servletMappings属性中

这里的检测思路就是在我们注册内存马的必要步骤中进行处理

Filter

针对于Filter型内存马的检测,采取的是和Servlet型类似的检测方法,也即是获取所有存在的Filter,之后判断资源文件是否存在

类似的,简单看一下两个关键的方法

getFilterConfig

ServletListenerFilter内存马查杀手段一

这个方法同样是获取了StandardContext对象之后获取其中的filterCon

figs属性值

这个属性值存放的也就是每一个filter的filterName -> applicationFilterConfig的一个映射,其中他的value值ApplicationFilterConfig对象中存放的是一些关于过滤器的配置内容,比如filterName / filterClass等等信息,在前面进行filter型内存马的编写的时候也涉及到了这个类对象的创建

ServletListenerFilter内存马查杀手段一

第二个方法是getFilterMaps

ServletListenerFilter内存马查杀手段一

类似的是获取的是StandardContext类对象中的filterMaps属性

ServletListenerFilter内存马查杀手段一

对于该属性的描述

此应用程序的过滤器映射集,按照它们在部署描述符中定义的顺序,以及通过 ServletContext 添加的额外映射,可能在部署描述符中定义的映射之前和之后。

在获取了和filter有关的信息之后,检测的主体是:

ServletListenerFilter内存马查杀手段一

  1. 遍历所有的filter

  2. 分别获取每一个filterfilterName / filterClass / filterClassLoaderName等等信息

  3. 最后在结果输出中,调用了classFileIsExists方法根据filterClass来判断是否存在有对应的filterClass的文件资源,有,则输出对应的path路径,没有,则说明可能为内存马

consideration

同样的,我们可以结合filter内存马的注入流程

只需要设置filterMaps、filterConfigs、filterDefs就可以注入恶意的filter

  • filterMaps:一个HashMap对象,包含过滤器名字和URL映射

  • filterDefs:一个HashMap对象,过滤器名字和过滤器实例的映射

  • filterConfigs变量:一个ApplicationFilterConfig对象,里面存放了filterDefs

这里的检测同样是根据注入的关键点进行检测

Listener

针对tomcat下的所有的listener的获取,涉及到的方法是getListenerList

ServletListenerFilter内存马查杀手段一

同样是在StandardContext对象中获取他的applicationEventListenersList属性值

ServletListenerFilter内存马查杀手段一

这个属性值存放的一些application event listener的列表

接下来对于检测listener型内存马的主题部分是

ServletListenerFilter内存马查杀手段一

这里在获取了所有的listener之后,在其中筛选出了ServletRequestListener的实现类作为检测的目标

至于什么是ServletRequestListener? 以及除了这类listener还有什么其他类型的监听器?

这些答案在前面进行listener内存马的构造一文中能够找到

因为这里仅仅是筛选了ServletRequestListener的实现类进行检测,虽然常见的Listener动态创建的监听器是这个实现类,但是如果选择其他类型的监听器进行内存马的注入,这是,如果采用这种方法将会出现检测不全的情况

ServletListenerFilter内存马查杀手段一

同样会对listener类进行是否存在类资源进行一定的检查

consideration

结合之前的listener型内存马的注入方式

内存马编写流程

  1. 首先获取到StardardContext对象

  2. 之后创建一个实现了ServletRequestListener 接口的监听器类

  3. 再然后通过调用StardardContext类的addApplicationEventListener方法进行Listener的添加

这里同样是通过对应的流程进行检测

Others

这里除了存在有是否是内存马的判断功能,还存在有servlet / filter / listener类的下载功能以及查杀功能

dump

ServletListenerFilter内存马查杀手段一

直接就是在通过Repository.lookupClass方法获取指定的类之后将其内存写入response body中返回

kill

这里分别采用不同的方式进行kill

针对servlet型是在deleteServlet方法中

ServletListenerFilter内存马查杀手段一

在简单的根据传入的HttpServletRequest / ServletClassName获取到了urlPattern / ServletClass等信息

  1. 通过反射调用StandardContext对象的removeServletMapping方法ServletListenerFilter内存马查杀手段一

    这个方法是用来根据路由删除注册的servlet

  2. 通过反射调用StandardContext对象的removeChild方法ServletListenerFilter内存马查杀手段一

    这个方法是为了不仅仅在前面删除掉路由和servlet的映射关系,也删除掉创建的对应的Wrapper对象

而针对Filter型的内存马,主要是在deleteFilter方法中

ServletListenerFilter内存马查杀手段一

  1. 获取一些关于filter的一些信息

  2. 之后就是获取FilterDef类对象之后,反射获取他的removeFilterDef方法,传入filterDef,也就是过滤器名字和过滤器实例的映射ServletListenerFilter内存马查杀手段一

    进行映射的移除

  3. 之后又是获取FilterMap类对象之后,反射获取他的removeFilterMap方法,调用进行过滤器名字和URL映射的删除ServletListenerFilter内存马查杀手段一

总的来说,servlet和filter的删除主要是针对在构造的过程中的一些反方向,在构造过程中添加了什么,在kill的过程中也将要将添加的内容通过调用对应的api进行删除

Conclusion

通过整个对Servlet / Listener / Filter型内存马的查杀的原理分析,能够知道这种方式也就是采用直接获取所有的servlet / Listener / Filter的目标类,进而判断是否存在有文件存在来判断

针对这类型的绕过,比如前面分析到的Listener型内存马的检查,这里仅仅是筛选了其中的一种Listener进行检测,这种方式可能会导致一些漏扫之类的问题,而且这种对于是否是内存马的判断是直接判断是否能够获取到对应类的文件,这种方式并没有判断该类文件的危害性,同样存在有漏扫和误报的情况在。

ServletListenerFilter内存马查杀手段一

原文始发于微信公众号(FreeBuf):ServletListenerFilter内存马查杀手段一

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年6月24日01:52:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   ServletListenerFilter内存马查杀手段一http://cn-sec.com/archives/1828562.html

发表评论

匿名网友 填写信息