漏洞概述
2020年2月20日,国家信息安全漏洞共享平台(CNVD)发布关于Apache Tomcat的安全公告,Apache Tomcat文件包含漏洞(CNVD-2020-10487,对应CVE-2020-1938)。
Tomcat AJP协议由于存在实现缺陷导致相关参数可控,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp下的任意文件。若服务器端同时存在文件上传功能,攻击者可进一步实现远程代码的执行。
由于
Tomcat
在处理AJP
请求时,未对请求做任何验证,通过设置AJP
连接器封装的request
对象的属性,导致产生任意文件读取漏洞和代码执行漏洞CVE-2020-1938 又名GhostCat, 之前引起了一场风雨,由e长亭科技安全研究员发现的存在于Tomcat中的安全漏洞,由于Tomcat AJP协议设计上存在缺陷,攻击者通过 Tomcat AJP Connector 可以读取或包含 Tomcat 上所有 webapp 目录下的任意文件,例如可以读取 webapp 配置文件或源代码。此外在目标应用有文件上传功能的情况下,配合文件包含的利用还可以达到远程代码执行的危害。
影响范围
Apache Tomcat 9.x < 9.0.31
Apache Tomcat 8.x < 8.5.51
Apache Tomcat 7.x < 7.0.100
Apache Tomcat 6.x
本次漏洞与三个include属性有关
javax.servlet.include.request_uri
javax.servlet.include.path_info
javax.servlet.include.servlet_path
任意文件读取
任意文件读取问题出现在org.apache.catalina.servlets.
DefaultServlet
这个Servlet
构造一个AJP请求,请求会走默认的DefaultServlet并交给
DefaultServlet
的doGet
方法处理。doGet
会调用ServeResource
方法获取资源文件,调用getRelativePath
方法获取要读取资源的相对路径,通过getResources
方法就可以获取到了对应路径的Web资源对象。
然后再通过控制ajp控制的上述三个include属性来读取文件,通过操控上述三个属性从而可以读取到/WEB-INF下面的所有敏感文件,不限于class、xml、jar等文件。
任意代码执行
任意代码执行问题出现在org.apache.jasper.servlet.
JspServlet
这个servlet
。构造一个如下的AJP请求,让Tomcat执行
/docs/test.jsp
,但实际上它会将code.txt当成jsp来解析执行。
RequestUri:/docs/test.jsp
javax.servlet.include.request_uri: /
javax.servlet.include.path_info: code.txt
javax.servlet.include.servlet_path: /
code.txt内容如下
<%
java.util.List<String> commands = new java.util.ArrayList<String>();
commands.add("/bin/bash");
commands.add("-c");
commands.add("/Applications/Calculator.app/Contents/MacOS/Calculator");
java.lang.ProcessBuilder pb = new java.lang.ProcessBuilder(commands);
pb.start();
%>
发送AJP请求,请求的是
/docs/test.jsp
这个jsp,但是由于那三个include属性可控,可以将test.jsp
对应的服务器脚本文件改为code.txt
,导致tomcat把我们的code.txt当jsp文件编译运行,导致代码执行。
TomcatAJP Connector以及AJP协议
Tomcat Connector 是 Tomcat 与外部连接的通道,它使得 Catalina 能够接收来自外部的请求,传递给对应的 Web 应用程序处理,并返回请求的响应结果。
默认情况下,Tomcat 配置了两个 Connector,它们分别是
HTTP Connector
和AJP Connector
:
// HTTP Connector:用于处理 HTTP 协议的请求(HTTP/1.1),默认监听地址为 0.0.0.0:8080
// AJP Connector:用于处理 AJP 协议的请求(AJP/1.3),默认监听地址为 0.0.0.0:8009
HTTP Connector 就是用来提供我们经常用到的 HTTP Web 服务。而 AJP Connector,它使用的是 AJP 协议(Apache Jserv Protocol),AJP 协议可以理解为 HTTP 协议的二进制性能优化版本,它能降低 HTTP 请求的处理成本,因此主要在需要集群、反向代理的场景被使用。
AJP是Apache Tomcat web服务器用来与servlet容器通信的一个二进制协议。主要用于集群或逆向代理场景,其中web服务器与应用服务器或servelet容器进行通信。
简单来说,就是HTTP Connector暴露给客户端了,AJP是webserver (如Apache HTTPD)和Apache Tomcat服务器之间内部使用的,如下图所示。AJP在Apache HTTP服务器中是以模块的形式实现的,表示为mod_jk或mod_proxy_ajp。AJP本身并不会暴露到外部,这也是下一部分要讨论的RCE场景的先决条件之一。
漏洞修复
升级版本
将Tomcat立即升级到9.0.31,8.5.51或7.0.100版本进行修复
升级步骤
1.下载要升级的Tomcat版本
wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.51/bin/apache-tomcat-8.5.51.tar.gz
2. 停止旧版本tomcat
cd /home/…/tomcat_8/bin
./shutdown.sh
# 创建新的tomcat路径,备份旧的tomcat服务
mkdir /home/…/tomcat_8_old
cp -Rf /home/…/tomcat_8/* /home/…/tomcat_8_old/
# 安装目录下解压新的tomcat
tar -zxvf apache-tomcat-8.5.51.tar.gz
# 删除旧的服务文件,将新的服务名称改成之前的
rm -rf tomcat_8
mv apache-tomcat-8.5.51 tomcat_8
# 用备份的server.xml替换新的server.xml
cd /home/…/tomcat_8/conf/
cp /home/…/tomcat_8_old/conf/server.xml ./
# 用备份的webapps替换新的webapps
cd /home/…/tomcat_8/
cp /home/…/tomcat_8_old/webapps ./
# 用备份的catalina.sh替换新的
cd /home/…/tomcat_8/bin/
cp /home/…/tomcat_8_old/bin/catalina. sh ./
# 我这里的备份路径下有一些日志信息也一并移过来
mv /home/…/tomcat_8_old/logs/* /home/…/tomcat_8/logs/
# 启动tomcat
cd /home/…/tomcat_8/bin
./startup.sh
隐藏版本
可以的话做一下隐藏版本信息
cd cd apache-tomcat-8.5.51/lib
unzip catalina.jar
vim ServerInfo.properties
# 自定义修改 server.number和server.built的配置
server.info=Apache Tomcat
server.number=sb
server.built=sb
cd /opt/apache-tomcat-8.5.51/lib
jar uvf catalina.jar org/apache/catalina/util/ServerInfo.properties
# 重启服务即可
tomcat在8.5.51版本做了如下修复
// 默认不开启AJP
// 默认只监听本地ip
// 强制设置认证secret
// 代码层面主要在AjpProcessor类的prepareRequest方法封装requst对象时采用了白名单,只添加已知属性。这样三个include属性不再被客户端控制,漏洞修复。
禁用AJP协议
编辑/conf/server.xml,找到如下行
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443" />
将此行注释掉(也可删掉该行)
<!--<Connectorport="8009" protocol="AJP/1.3"redirectPort="8443" />-->
配置secret来设置AJP协议的认证凭证
例如(注意将您的tomcat_ajp_secret更改为一个安全性高,无法被轻易猜解的值)
<Connector port="8009"protocol="AJP/1.3" redirectPort="8443"address="YOUR_TOMCAT_IP_ADDRESS" secret="YOUR_TOMCAT_AJP_SECRET"/>
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan