CVE-2019-0232:Apache Tomcat RCE漏洞分析
字数 1542 2025-08-29 08:32:18
Apache Tomcat CVE-2019-0232 RCE漏洞分析与防护指南
漏洞概述
CVE-2019-0232是Apache Tomcat中的一个远程代码执行漏洞,影响Windows平台上的CGI Servlet功能。该漏洞源于Tomcat CGI将命令行参数传递给Windows程序的方式存在缺陷,导致可能被命令注入攻击。
影响范围
- Apache Tomcat 9.0.0.M1 至 9.0.17
- Apache Tomcat 8.5.0 至 8.5.39
- Apache Tomcat 7.0.0 至 7.0.93
漏洞利用前提条件
- 操作系统限制:仅影响Windows平台
- 配置要求:
- 启用了CGIServlet
- 设置了enableCmdLineArguments参数为true
- 默认安全性:CGIServlet和enableCmdLineArguments参数默认情况下都不启用
漏洞复现步骤
环境准备
- Tomcat版本:9.0.12
- JRE版本:1.8.0
配置步骤
- 启用CGIServlet(修改conf/web.xml):
<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映射(conf/web.xml):
<servlet-mapping>
<servlet-name>cgi</servlet-name>
<url-pattern>/cgi-bin/*</url-pattern>
</servlet-mapping>
- 修改Context权限(conf/context.xml):
<Context privileged="true">
<!-- 原有内容保持不变 -->
</Context>
- 创建CGI脚本:
- 在ROOT/WEB-INF下创建cgi-bin目录
- 创建e.bat文件,内容为:
echo Content-type: text/html
漏洞验证
访问URL:http://127.0.0.1:8080/cgi-bin/e.bat?&ver
漏洞原理分析
技术背景
漏洞存在于tomcat/java/org/apache/catalina/servlets/CGIServlet.java中,当启用enableCmdLineArguments参数时,CGIServlet会根据RFC 3875从URL参数生成命令行参数,并通过Java的Runtime执行。
Windows与Linux执行差异
-
Windows执行机制:
- 使用
CreateProcess创建进程 - 参数合并为字符串作为
lpComandLine传入 - 对于.bat或.cmd文件,会调用
cmd.exe执行 - 最终格式:
cmd.exe /c "arg.bat & dir"
- 使用
-
Linux执行机制:
- 使用
execve系统调用 - 参数直接传递,不会进行命令解释
- 示例调用:
execve("arg.sh", ["arg.sh", "arg"dir"], [/* 23 vars */])
- 使用
Windows参数处理特性
-
引号处理问题:
- Windows将
"中的内容拷贝为下一个参数,直到遇到下一个" - 对
\"处理存在缺陷,可能导致参数逃逸
- Windows将
-
示例:
dir "\"&whoami"在Windows中会执行命令- 同样的命令在Linux中是安全的
修复方案
官方修复
-
新增参数校验:
- 添加
cmdLineArgumentsDecoded参数 - 对传入的命令行参数进行模式匹配校验
- 添加
-
校验代码:
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;
}
- 执行控制:
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);
}
修复版本说明
- 虽然9.0.18修复了该漏洞,但该更新未通过候选版本投票
- 建议用户升级至9.0.19或更高版本
防护建议
-
升级Tomcat:
- 升级到不受影响的版本(9.0.19+、8.5.40+、7.0.94+)
-
配置调整:
- 关闭
enableCmdLineArguments参数(设置为false) - 如非必要,禁用CGIServlet功能
- 关闭
-
安全实践:
- 最小化Tomcat运行权限
- 定期审查服务器配置
- 监控可疑的CGI请求