内存的检测与排查

内存🐎的检测与排查

查杀Java Web filter型内存马

0x01 内存马简历史

其实内存马由来已久,早在17年n1nty师傅的《Tomcat源码调试笔记-看不见的shell》中已初见端倪,但一直不温不火。后经过rebeyong师傅使用agent技术加持后,拓展了内存马的使用场景,然终停留在奇技淫巧上。在各类hw洗礼之后,文件shell明显气数已尽。内存马以救命稻草的身份重回大众视野。特别是今年在shiro的回显研究之后,引发了无数安全研究员对内存webshell的研究,其中涌现出了LandGrey师傅构造的Spring controller内存马。至此内存马开枝散叶发展出了三大类型:

  1. servlet-api类
    • filter型
    • servlet型
  1. spring类
    • 拦截器
    • controller型
  1. Java Instrumentation类
    • agent型
0x02 查杀思路

利用Java Agent技术遍历所有已经加载到内存中的class。先判断是否是内存马,是则进入内存查杀。

0x03 内存马的识别

1.filter名字很特别【弱特征】

内存马的Filter名一般比较特别,有shell或者随机数等关键字。这个特征稍弱,因为这取决于内存马的构造者的习惯,构造完全可以设置一个看起来很正常的名字。

2.filter优先级是第一位【弱特征】

为了确保内存马在各种环境下都可以访问,往往需要把filter匹配优先级调至最高,这在shiro反序列化中是刚需。但其他场景下就非必须,只能做一个可疑点。

对于一个web工程的filter过滤器,一般有两种方式放入项目中:

1、在web.xml里面配置

之前我们控制多个filter的执行顺序是通过web.xml中控制filter的位置来控制的,放在上面的会比放在下面的先执行,如下“用户登录检查过滤器”会比“接口日志过滤器”先执行。

<!-- 用户登录检测过滤器 -->
<filter>
	<filter-name>UserLoginFilter</filter-name>
	<filter-class>net.tfgzs.demo.filter.UserLoginFilter</filter-class>
</filter>
<filter-mapping>
	<filter-name>UserLoginFilter</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
<!--接口日志过滤器-->
<filter>
	<filter-name>ApiLog</filter-name>
	<filter-class>net.tfgzs.demo.filter.ApiLog</filter-class>
</filter>
<filter-mapping>
	<filter-name>ApiLog</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

2、@WebFilter注解

注解里面没有提供可以控制执行顺序的参数,通过实践发现如果想要控制filer的执行顺序可以 通过控制filter的文件名的首字母来 来控制。

比如:

UserLoginFilter.java 和 ApiLog.java 这两个文件里面分别是“用户登录检查过滤器”和“接口日志过滤器”,因为这两个文件的 首字母A排U之前 ,导致每次执行的时候都是先执行“接口日志过滤器”再执行“用户登录检查过滤器”。

3.对比web.xml中没有filter配置【强特征】

内存马的Filter是动态注册的,所以在web.xml中肯定没有配置,这也是个可以的特征。但servlet 3.0引入了@WebFilter标签方便开发这动态注册Filter。这种情况也存在没有在web.xml中显式声明,这个特征可以作为较强的特征。

4.特殊classloader加载【弱特征】

我们都知道Filter也是class,也是必定有特定的classloader加载。一般来说,正常的Filter都是由中间件的WebappClassLoader加载的。反序列化漏洞喜欢利用TemplatesImpl和bcel执行任意代码。所以这些class往往就是以下这两个:

  • com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader

  • com.sun.org.apache.bcel.internal.util.ClassLoader

这个特征是一个特别可疑的点了。当然了,有的内存马还是比较狡猾的,它会注入class到当前线程中,然后实例化注入内存马。这个时候内存马就有可能不是上面两个classloader。

5.对应的classloader路径下没有class文件【强特征】

所谓内存马就是代码驻留内存中,本地无对应的class文件。所以我们只要检测Filter对应的ClassLoader目录下是否存在class文件。

private static boolean classFileIsExists(Class clazz){
    if(clazz == null){
        return false;
    }

    String className = clazz.getName();
    String classNamePath = className.replace(".", "/") + ".class";
    URL is = clazz.getClassLoader().getResource(classNamePath);
    if(is == null){
        return false;
    }else{
        return true;
    }
}

6.Filter的doFilter方法中有恶意代码【强特征】

我们可以把内存中所有的Filter的class dump出来,使用fernflower等反编译工具分析看看,是否存在恶意代码,比如调用了如下可疑的方法:

  • java.lang.Runtime.getRuntime

  • defineClass

  • invoke

不难分析,内存马的命门在于56。简单说就是Filter型内存马首先是一个Filter类,同时它在硬盘上没有对应的class文件。若dump出的class还有恶意代码,那是内存马无疑。

0x04 内存马的查杀

java-memshell-scanner

通过jsp脚本扫描并查杀各类中间件内存马,比Java agent要温和一些。

未注入内存马之前:

img

注入内存马后:

img

点击kill,杀掉内存马

img

再次访问已经无法执行命令

img

tomcat有一个work目录,里面存放了页面的缓存,访问的jsp都会编译(从 work里进入Catalina后的如localhost站点文件夹下的项目,我们可以看到那些jsp页面会被编译成应该是servlet文件,下次再来 访问时,就直接运行servlet类就可以向客户端反应响应页面了,所以有的博客说第一次访问时会比较慢,是因为新发布上去的页面在第一个人访问时,会先 编译成servlet文件,所以慢了,一旦编译好,那么除非jsp页面修改,不然下次访问直接运行servlet就可以响应用户,所以快),编译后的文件都会存储在work目录下。而tomcat显示的目录,都会从这个缓存里找编译后的jsp对应的class文件。所以当清空了work目录后,该过程将会从新来过。

  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值