CVE-2019-0232:Apache Tomcat RCE漏洞分析

2019-04-23 约 1235 字 预计阅读 3 分钟

声明:本文 【CVE-2019-0232:Apache Tomcat RCE漏洞分析】 由作者 lyle 于 2019-04-23 10:30:00 首发 先知社区 曾经 浏览数 181 次

感谢 lyle 的辛苦付出!

简介

利用前提

该漏洞是由于Tomcat CGI将命令行参数传递给Windows程序的方式存在错误,使得CGIServlet被命令注入影响。

该漏洞只影响Windows平台,要求启用了CGIServlet和enableCmdLineArguments参数。但是CGIServlet和enableCmdLineArguments参数默认情况下都不启用。

时间线

  • 报告漏洞 2019-3-3
  • 漏洞公开 2019-4-10

漏洞影响范围

  • 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

复现

笔者使用的复现环境为9.0.12 + JRE 1.8.0。

首先进行CGI相关的配置,在 conf/web.xml 中启用CGIServlet:

<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>

这里主要的设置是 enableCmdLineArgumentsexecutable 两个选项。 enableCmdLineArguments 启用后才会将Url中的参数传递到命令行, executable 指定了执行的二进制文件,默认是 perl,需要置为空才会执行文件本身。

同样在 conf/web.xml 中启用cgi的servlet-mapping

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

之后修改 conf/context.xml<Context> 添加 privileged="true"属性,否则会没有权限

<Context privileged="true">

    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
</Context>

然后在 ROOT\WEB-INF 下创建 cgi-bin 目录, 并在该目录下创建一个内容为 echo Content-type: text/htmle.bat 文件。

配置完成后,启动tomcat,访问 http://127.0.0.1:8080/cgi-bin/e.bat?&ver ,可以看到命令执行成功。

原理

漏洞相关的代码在 tomcat\java\org\apache\catalina\servlets\CGIServlet.java 中,CGIServlet提供了一个cgi的调用接口,在启用enableCmdLineArguments参数时,会根据RFC 3875来从Url参数中生成命令行参数,并把参数传递至Java的 Runtime 执行。 这个漏洞是因为Windows下参数处理的特性导致的,具体的处理方式可以看微软的这篇文章

下面以一个简单的case来说明这个问题,在Windows下创建arg.bat

rem arg.bat
echo %*

并执行如下的Java代码

String [] cmd={"arg.bat", "arg", "&", "dir"};
Runtime.getRuntime().exec(cmd);

在Windows下会输出 argdir 命令运行后的结果。

同样的,用类似的脚本在Linux环境下测试:

# arg.sh
for key in "$@"
do
    echo '$@' $key
done
String [] cmd={"arg.sh", "arg", "&", "dir"};
Runtime.getRuntime().exec(cmd);

此时的输出为

$@ arg
$@ &
$@ dir

这个例子可以比较清晰的看出漏洞的成因。

修复方式

开发者在 patch 中增加了 cmdLineArgumentsDecoded 参数,这个参数用来校验传入的命令行参数,如果传入的命令行参数不符合规定的模式,则不执行。

校验写在 setupFromRequest 函数中:

String decodedArgument = URLDecoder.decode(encodedArgument, parameterEncoding);
if (cmdLineArgumentsDecodedPattern != null &&
        !cmdLineArgumentsDecodedPattern.matcher(decodedArgument).matches()) {
    if (log.isDebugEnabled()) {
        log.debug(sm.getString("cgiServlet.invalidArgumentDecoded",
                decodedArgument, cmdLineArgumentsDecodedPattern.toString()));
    }
    return false;
}

不通过时,会将 CGIEnvironmentvalid 参数设为 false ,在之后的处理函数中会直接跳过执行。

if (cgiEnv.isValid()) {
    CGIRunner cgi = new CGIRunner(cgiEnv.getCommand(),
                                  cgiEnv.getEnvironment(),
                                  cgiEnv.getWorkingDirectory(),
                                  cgiEnv.getParameters());

    if ("POST".equals(req.getMethod())) {
        cgi.setInput(req.getInputStream());
    }
    cgi.setResponse(res);
    cgi.run();
} else {
    res.sendError(404);
}

修复建议

  1. 使用更新版本的Apache Tomcat。这里需要注意的是,虽然在9.0.18就修复了这个漏洞,但这个更新是并没有通过候选版本的投票,所以虽然9.0.18没有在被影响的列表中,用户仍需要下载9.0.19的版本来获得没有该漏洞的版本。
  2. 关闭enableCmdLineArguments参数

参考链接

关键词:[‘安全技术’, ‘漏洞分析’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now