Tomcat Ajp协议文件包含漏洞分析
字数 2113 2025-08-26 22:12:03
Tomcat AJP协议文件包含漏洞(CVE-2020-1938)深入分析与防御指南
漏洞概述
漏洞编号: CVE-2020-1938 / CNVD-2020-10487
漏洞类型: 文件包含漏洞
影响范围:
- Apache Tomcat 6
- Apache Tomcat 7 < 7.0.100
- Apache Tomcat 8 < 8.5.51
- Apache Tomcat 9 < 9.0.31
漏洞描述: 攻击者可以利用该漏洞读取或包含Tomcat上所有webapp目录下的任意文件,包括webapp配置文件或源代码等敏感信息。在特定条件下,还可实现远程代码执行(RCE)。
漏洞背景知识
Tomcat架构简介
Tomcat的整体架构包含以下关键组件:
- Server: 一个Tomcat实例就是一个Server
- Service: 每个Server可以包含多个Service(逻辑层)
- Connector: 处理客户端请求的组件
- Container: 包含多个Host(虚拟主机)
- 每个Host对应一个域名
- 每个Host可包含多个Context(Web应用)
- 每个Context包含多个Wrapper(封装Servlet)
关键配置文件
-
conf/server.xml: 定义Tomcat启动时的组件属性
- 包含两个重要的Connector:
<!-- HTTP Connector --> <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> <!-- AJP Connector --> <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> - Tomcat启动后会监听8080(HTTP)和8009(AJP)端口
- 包含两个重要的Connector:
-
conf/web.xml: 定义Servlet配置
- 包含两个关键的内建Servlet:
DefaultServlet: 处理所有未被匹配到其他servlet的URI请求JspServlet: 处理以.jsp/.jspx为后缀的URI请求
- 包含两个关键的内建Servlet:
AJP协议简介
AJP(Apache JServ Protocol)是建立在TCP之上的二进制协议,主要用于Tomcat与前端的Web服务器(如Apache HTTP Server)通信。相比HTTP协议,AJP协议效率更高。
漏洞详细分析
漏洞成因
漏洞主要存在于Tomcat处理AJP协议的代码中,攻击者可以通过构造特殊的AJP请求控制request对象的某些属性,进而实现文件包含。
关键代码分析
-
AJP请求处理(org.apache.coyote.ajp.AjpProcessor)
service()方法调用prepareRequest()解析请求头- 当AJP数据包头设置为
SC_REQ_ATTRIBUTE时,Connector会读取属性名(n)和值(v) - 当n不是
SC_A_REQ_LOCAL_ADDR、SC_A_REQ_REMOTE_PORT或SC_A_SSL_PROTOCOL时,会用v来赋值属性n
-
DefaultServlet处理流程
- 当请求URI无法匹配其他servlet时,由
DefaultServlet处理 - 调用链:
service()→doGet()→serveResource() getRelativePath()方法从request对象获取以下属性控制路径:javax.servlet.include.request_uri javax.servlet.include.path_info javax.servlet.include.servlet_path- 攻击者可通过AJP协议控制这些属性来读取任意文件
- 当请求URI无法匹配其他servlet时,由
-
JspServlet处理流程
- 对于.jsp/.jspx请求,由
JspServlet处理 service()方法通过可控属性构造jspUri:String jspUri = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); if (jspUri == null) { jspUri = request.getServletPath(); }- 后续会编译jsp文件生成servlet,实现文件包含
- 对于.jsp/.jspx请求,由
漏洞利用方式
-
任意文件读取
- 通过控制
DefaultServlet处理的路径,读取webapp目录下的任意文件 - 包括配置文件、源代码等敏感信息
- 通过控制
-
远程代码执行(RCE)
- 前提: 能上传可控内容到webapp目录(如头像上传功能)
- 步骤:
- 上传包含恶意JSP代码的文件(如evilman.png)
- 通过AJP协议包含该文件
- Tomcat会将其作为JSP编译执行
漏洞复现
环境准备
- 受影响Tomcat版本(如8.5.40)
- 内网测试环境(IP: 10.0.12.93)
复现步骤
-
任意文件下载测试
- 使用公开POC工具
- 成功读取webapp目录下的文件
-
文件包含到RCE
- 在
webapps/examples/下创建evilman.png,内容为:<% out.println(new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec("whoami").getInputStream())).readLine()); %> - 通过AJP协议包含该文件
- 成功执行系统命令,验证漏洞
- 在
-
查看编译结果
- 编译后的jsp代码位于:
work/Catalina/localhost/examples/org/apache/jsp/ - 可查看生成的servlet代码
- 编译后的jsp代码位于:
防御措施
-
升级Tomcat
- 升级到安全版本:
- Tomcat 7 ≥ 7.0.100
- Tomcat 8 ≥ 8.5.51
- Tomcat 9 ≥ 9.0.31
- 升级到安全版本:
-
临时解决方案
- 禁用AJP协议:
修改conf/server.xml,注释掉8009端口的Connector:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->
- 禁用AJP协议:
-
其他防护建议
- 限制AJP端口的访问(如防火墙规则)
- 定期检查服务器上的可疑文件
- 加强文件上传功能的安全检查