TomcatAJP文件包含漏洞及线上修复漏洞

漏洞概述

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并交给DefaultServletdoGet方法处理。
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 ConnectorAJP 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

相关文章

遵循Java Servlet 规范第4节中的建议 ,Apache Tomcat实现了...
JMX(Java管理扩展)是一项非常强大的技术,可让您管理,监视...
总览介绍 建立 取得Java 获取TomCat 将TomCat安装为Window...
PSI Probe是Lambda Probe的社区驱动分支,使用相同的开源许可...