[备份]探索Filter型Tomcat内存马的免杀

介绍

学习了c0ny1师傅写的查杀Java web filter型内存马

Filter型内存马的查杀思路主要是这四条:

  1. Filter名称是否合理
  2. Filter对应的类名是否合理
  3. Filter对应的类是否在classpath
  4. 网站web.xml中是否存在改filter

笔者想办法绕过了这四条的验证

先来看看已有内存马查杀工具的效果

比如天下大木头师傅的查杀截图:

arthas

img

copagent

img

比较好用的java-memshell-scanner

img

 

效果

有针对性地对四条检测进行分析,最终能够达到以下的效果

  1. 模拟看似合法的filter,例如shiroFilteruserFilter
  2. 读取已有filter的包名(例如这里的org.sec.tomcat)然后修改恶意filter的包名一致
  3. 重要的一点:恶意filter在classpath中是真实存在

img

  1. 随机生成合理的filter的名字和filter对应的类名

img

  1. 自动修改web.xml中的内容(编译后的web.xml)

img

通过以上5步可以做到:

如果防御人员对后端业务逻辑代码没有比较深入的掌握情况下是无法查出内存马的

哪怕借助工具也很难查杀

 

重命名

首先第一步是对已有业务Filter的信息做收集,以确实恶意的filter需要怎样命名

排除org.apache.tomcat包下的系统Filter只考虑项目包的自定义Filter

(核心代码参考c0ny1师傅的java-memshell-scanner

从常见filter列表里确定新的名字,需要和tomcat已有的名字不冲突

实际上这个nameArray数组可以设置为可配置的,自行根据目标业务逻辑编写

 

动态字节码

根据以上收集到的信息,将字节码写入指定位置

例如项目的包名是com.test.project,模拟的类名是UserFilter,那么就需要构造出恶意的字节码,写入.../classes/com/test/project/UserFilter.class

上文的getFilter函数其实是重点部分,作用是根据类名生成字节码

动态生成字节码就要借助ASM框架,代码如下

其实复杂的ASM代码,本质是生成以下这样的类的字节码

生成字节码后写入classpath中对应的地方,加载和实例化Filter的时候直接Class.forName就可以

 

修改配置

最后一步就是修改web.xml的配置了

虽然修改的是编译后的web.xml,但是防御人员一般没有源码审计,只能审计编译后的字节码和web.xml文件

 

总结

难点在于动态字节码,其他部分做起来不算复杂

一个思考:该手段是否有可能导致内存马的持久化呢?

已经写入了目标的classpath,由于模拟配置了web.xml,是否会导致第二次启动直接加载了恶意Filter

后来笔者挖某知名框架内存马时,摸索出一种进阶的内存马免杀:将恶意代码隐藏到框架必须的Filter中

将在后续的文章中和大家分享

笔者目前本科在读,才疏学浅,错误和不足之处还请大佬指出,十分感谢!