Tomcat AJP 文件包含漏洞(CVE-2020-1938)

article/2025/8/30 4:03:50

目录

1.漏洞简介

2、AJP13 协议介绍

Tomcat 主要有两大功能:

3.Tomcat 远程文件包含漏洞分析

4.漏洞复现

 5、漏洞分析

6.RCE 实现的原理

1.漏洞简介


  • 2020 2 20 日,公开CNVD 的漏洞公告中发现 Apache Tomcat 文件包含漏洞(CVE-2020-1938)。
  • Apache Tomcat Apache 开源组织开发的用于处理 HTTP 服务的项目。Apache Tomcat 服务器中被发现存在文件包含漏洞,攻击者可利用该漏洞读取或包含 Tomcat上所有 webapp 目录下的任意文件。
  • 该漏洞是一个单独的文件包含漏洞,依赖于 Tomcat AJP(定向包协议)AJP自身存在一定缺陷,导致存在可控参数,通过可控参数可以导致文件包含漏洞。AJP协议使用率约为 7.8%,鉴于 Tomcat 作为中间件被大范围部署在服务器上,该漏洞危害较大。

2、AJP13 协议介绍


Tomcat 主要有两大功能:

  • 一是充当 Web 服务器,可以对一切静态资源的请求作出回应;常见的 Web 服务器有 ApacheNginxIIS
  • 二是充当 Servlet 容器常见的 Servlet 容器有 TomcatWeblogicJBOSS
        Servlet 容器可以理解为 Web 服务器的升级版。以 Tomcat 为例, Tomcat 本身可以不作为 Servlet 容器使用,仅仅充当 Web 服务器的角色,但是其处理静态资源请求的效率和速度远不及 Apache ,所以很多情况下生产环境会将 Apache 作为 Web 服务器来接收用户的请求。静态资源由 Apache 直接处理,而 Servlet 请求则交由 Tomcat来进行处理。这种方式使两个中间件各司其职,大大加快了响应速度。
        众所周知,用户的请求是以 HTTP 协议的形式传递给 Web 服务器。我们在浏览器中对某个域名或者 ip 进行访问时,头部都会有 http 或者 https 的表示,而 AJP 浏览器是不支持的,我们无法通过 浏览器发送 AJP 的报文。AJP 这个协议并不是提供给用户使用的。
  • Tomcat$ CATALINA_BASE/conf/web.xml 默认配置了两个 Connector,分别监听两个不同的端口,一个是 HTTP Connector 默认监听 8080 端口,另一个是 AJP Connector 默认监听 8009 端口。
  • HTTP Connector 主要负责接收来自用户的请求,包括静态请求和动态请求。有了 HTTP ConnectorTomcat 才能成为一个 Web 服务器,还可以额外处理 Servlet 和JSP。
  • AJP 的使用对象通常是另一个 Web 服务器,例如 Apache,这里以下图进行说明。
Apache 服务器

 

  • AJP 是一个二进制TCP 传输协议。浏览器无法使用 AJP,而是首先由 Apache 与 Tomcat 进行 AJP 的通信,然后由 Apache 通过 proxy_ajp 模块进行反向代理,将其转换成 HTTP 服务器再暴露给用户,允许用户进行访问。
  • 这样做的原因是,相对于 HTTP 纯文本协议来说,效率和性能更高,同时也做了很多优化。在某种程度上,AJP 可以理解为 HTTP 的二进制版,因加快传输效率被广泛应用。实际情况是类似 Apache 这样有 proxy_ajp 模块可以反向代理 AJP 协议的服务器很少,所以 AJP 协议在生产环境中也很少被用到。

3.Tomcat 远程文件包含漏洞分析


        
首先从官网下载对应的 Tomcat 源码文件和可执行文件,如下图 所示
下载 Tomcat 源码文件和可执行文件

 

两个文件夹下载好后,存放入在同一个目录下,然后在源码中新增 pom.xml ,并添加以下内容
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.
org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.apache.tomcat</groupId> <artifactId>Tomcat8.0</artifactId> <name>Tomcat8.0</name> <version>8.0</version> <build> <finalName>Tomcat8.0</finalName> <sourceDirectory>java</sourceDirectory> <testSourceDirectory>test</testSourceDirectory> <resources> <resource> <directory>java</directory> </resource> </resources> <testResources> <testResource> <directory>test</directory> </testResource> </testResources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3</version> <configuration> <encoding>UTF-8</encoding><source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.easymock</groupId> <artifactId>easymock</artifactId> <version>3.4</version> </dependency> <dependency> <groupId>ant</groupId> <artifactId>ant</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>wsdl4j</groupId> <artifactId>wsdl4j</artifactId> <version>1.6.2</version> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>jaxrpc</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.eclipse.jdt.core.compiler</g
roupId> <artifactId>ecj</artifactId> <version>4.5.1</version> </dependency> </dependencies> 
</project>

然后添加一个 Application,如下图所示

  •  新增 Application 的配置信息。
  • Man class:中填入:org.apache.catalina.startup.Bootstrap
  • VMoptions:中填入:-Dcatalina.home="apache-tomcat-8.5.34",并将 catalina.
  • home 替换成 tomcat binary core 的目录。
  • JDK 默认是 1.8,因为我安装的是 jdk1.8 版本。
  • 启动过程中 Test 模块会报错,且为 TestCookieFilter.java,注释里面的测试内容即可。
  • 然后访问 127.0.0.1:8080,如出现以下页面,则表示环境搭建成功,如下图所示。
环境搭建成功

 

4.漏洞复现


任意文件读取漏洞复现,如下图
读取文件

 RCE 如图 4-1 和图 4-2 所示

图 4-1 RCE(一)

 

图 4-2 RCE(二)

 5、漏洞分析


首先定位到类 org.apache.coyote.ajp.AjpProcessor。根据网上透漏的漏洞消息,得知漏洞的产生是由于 Tomcat ajp 传递过来的数据的处理方式存在问题,导致用户可以控制

  1. “javax.servlet.include.request_uri
  2. javax.servlet.include.path_info
  3. javax. servlet.include.servlet_path”

3 个参数,从而读取任意文件,甚至可以进行 RCE

我们先从任意文件读取开始分析。环境使用 Tomcat 8.0.50 版本搭建,产生漏洞的原因并不在于 AjpProcessor.prepareRequest() 方法。 8.0.50 版本的漏洞点存在于AjpProcessor 的父类,即 AbstractAjpProcessor 抽象类的 prepareRequest() 中,如下图 5-1  所示
图 5-1 漏洞点分析

 在这里设置断点,然后运行 exp,查看此时的调用链,如下图所示

图 5-2 设置断点并运行 exp

 由于此次数据传输使用的是 AJP,经过 8009 口,并非我们常见的 HTTP,因此首先由内部类 SocketPeocessore 来进行处理。

处理完成后,经过几次调用交由 AbstractAjpProcessor.prepareRequest() 方法,该方法是漏洞产生的第一个点,如图 5-3  所示
图 5-3  漏洞产生的第一个点

         单步执行 request.setAttribute()方法,如图 5-4 和图 5-5 所示

图 5-4 单步执行 request.setAttribute()方法(一)

 

图 5-5  单步执行 request.setAttribute()方法(二)

 

这里我们可以看到, attributes 是一个 HashMap ,将通过 AJP 传递过来的 3 个参数循环遍历存入这个 HashMap ,如图 5-6  所示。
图 5-6 存储 3 个参数的 HashMap

 可以看到这里是一个 while 循环,直接来看循环完成后的结果,如图 5-7 所示

图 5-7  while 循环完成后的结果

 

先来查看 exp 发出的数据包,如图 5-8  所示
图 5-8 exp 发出的数据包

 通过使用 WireShark 抓包查看 AJP 报文的信息,其中有 4 个比较重要的参数如下。

URI:/asdf 
javax.servlet.include.request_uri:/ 
javax.servlet.include.path_info: WEB-INF/Test.txt 
javax.servlet.include.servlet_path:/
通过 AJP 传来的数据需要交由 Servlet 进行处理,那么应该交由哪个 Servlet 呢?
通过阅读关于 Tomcat 架构的文章和资料得知, Tomcat$ CATALINA_BASE/conf/web.xml 配置文件中默认定义了两个 Servlet :一个是 DefaultServlet ,如图 5-9所示;另一个是 JspServlet ,如图 5-92 所示。
图 5-9 默认定义的 DefaultServlet

 

图 5-10 默认定义的 JspServlet

         由于$ CATALINA_BASE/conf/web.xml 文件是 tomcat 启动时默认加载的,因此二个Servlet 会默认存放在 Servlet 容器中。当用户请求的 URI 不能与任何 Servlet 匹配时,会默认交由 DefaultServlet 来处理。DefaultServlet 主要用于处理静态资源,如 HTML、图片、CSSJS 文件等,而且为了提升服务器性能,Tomcat 将对访问文件进行缓存。按照默认配置,客户端请求路径与资源的物理路径是一致的。

        我们看到请求的 URI 为“ /asdf ”,符合无法匹配后台任何 Servlet 的条件。这里需要注意的是,举例来说,我们请求一个“abc.jsp ”,但是后台没有“ abc.jsp ”,这不属于无法匹配任何 Servlet ,因为 .jsp 的请求会默认由 JspServlet 进行处理,如图 5-11 所示。
图 5-11  无法匹配任何 Servlet

 根据上述内容,结合发送数据包中的“URI:/asdf”这一属性,可以判断该请求是由 DefaultServlet 进行处理的。

        定位到 DefaultServlet doGet 方法,如图 5-12   所示。
图 5-12  定位到 DefaultServlet 的 doGet 方法

 doGet 方法中调用了 serveResource()方法。serveResource()方法调用了 getRelativePath()

方法来进行路径拼接,如图 5-13  所示
图 5-13 路径拼接

这里就是将传入的 path_info servlet_path 进行复制的地方。 request_uri 用来做判断,如果发送的数据包中没有 request_uri,就会执行 else 后面的两行代码进行赋值。这会导致漏洞利用失败,如图 5-14 所示
图 5-14  执行代码进行赋值

 

接下来是对路径的拼接。这里可以看到,如果传递数据时不传递 servlet_path ,则 result 在进行路径拼接时不会将“/”拼接在“ WEB-INF/web.xml ”的头部。最后拼接的结果仍然是“WEB-INF/web.xml ”,如图 5-15  所示
图 5-15 拼接结果仍然是“WEB-INF/web.xml”

返回 DefaultServle.serveResource() 。然后判断 path 变量长度是否为 0 ,为 0 则调
目录重定向方法,如图 5-16  所示。

 

图 5-16  调用目录重定向方法

 

下面的代码开始读取指定的资源文件,如图 5-17  和图 5-18  所示:
图 5-17 读取指定的资源文件
图 5-18 resources 对象

 

 执行 StandardRoot.getResource()方法,如图 5-19 所示

图 5-19 执行 StandardRoot.getResource()方法

 getResource()方法中调用了很重要的 validate()方法,并将 path 作为变量传递进去进行处理。这里会涉及不能通过“/../../”的方式来读取 webapp 目录的上层目录中的文件的原因。首先是正常请求流程,如图 5-20  所示。

图 5-20 正常请求流程

 我们可以看到正常请求后 return result 路径就是文件所在的相对路径。 当我们尝试使用 WEB-INF/../../Test.txt 来读取 webapp 以外的目录中的文件时, 可以看到此时返回的 result null,而且会抛出异常,如图 5-21 所示

图 5-21 尝试目录穿越(一)

 所有原因都在于 RequestUtil.normalize()函数对我们传递进来的路径的处理方式。

关键的点就在下面的截图代码中。我们传入的路径是“ /WEB-INF/../../Test.txt , 首先程序会判断路径中是否存在“/../ ”,答案是包含且索引大于 8 ,所以第一个 if 判断不会成功,也不会跳出 while 循环。此时处理我们的路径,截取“/WEB-INF/..”以后的内容。然后 String,indexOf()函数判断路径中是否包含“/../ ”,答案是包含且索引为零,符合第二个 if 判断的条件,返回 null ,如图 5-21  所示
图 5-21  尝试目录穿越(二)

    ·此处的目标是不允许传递的路径的开头为“/../”,且不允许同时出现两个连在一起的“/../”,所以我们最多只能读取到 webapp 目录,无法读取 webapp 以外的目录中的文件。

        要读取 webapp 目录下的其余目录内的文件,可以通过修改数据包中的“ URI ”参数来实现,如图 5-22  所示
图 5-22 修改 URI

 程序最终会拼接出我们所指定文件的绝对路径,并作为返回值返回,如图 5-23 所示。

图 5-23 成功拼接文件路径

 

接下来回到 getResource() 函数进行文件读取,如图 5-24  所示
图 5-24 文件读取

 

以下是任意文件读取的调用链,如图 5-25  所示
图 5-25 任意文件读取的调用链

 

6.RCE 实现的原理


        前面介绍过 Tomcat$ CATALINA_BASE/conf/web.xml 配置文件中默认定义了两个 Servlet 。上述任意文件读取利用了 DefaultServlet,而 RCE 则需要用到 JspServlet 。 默认情况下,JspServlet url-pattern .jsp .jspx ,因此它负责处理所有 JSP 文件的请求。
JspServlet 主要完成以下工作:
  • 根据 JSP 文件生成对应 Servlet Java 代码(JSP 文件生成类的父类 org.apache.jasper.runtime.HttpJspBase——实现了 Servlet 接口)。
  • Java 代码编译为 Java 类。
  • 构造 Servlet 类实例并且执行请求。
  1. RCE 本质是通过 JspServlet 来执行我们想要访问的.jsp 文件。
  2. RCE 的前提是,首先想办法将包含需要执行的命令的文件(可以是任意文件后缀,甚至没有后缀)上传到 webapp 的目录下,才能访问该文件;然后通过 JSP 模板的解析造成 RCE。
        查看本次发送的 AJP 报文的内容,如图 6 -1  所示
图 6-1 AJP 报文的内容

 

        这里的“URI ”参数必须以“ .jsp ”结尾,但是该 JSP 文件可以不存在。
        其余 3 个参数与之前的没有区别,“ path_info ”参数对应的是我们上传的包含 JSP代码的文件。
        定位到 JspServlet.Service() 方法,如图 6-2  所示。
图 6-2 定位到 JspServlet.Service()方法
        首先,将“servlet_path ”的值取出赋值给变量 jspUri ,如图 6-3  所示

 

图 6-3  赋值给变量 jspUri

 

        然后,将“path_info ”参数对应的值取出并赋值给“ pathInfo ”变量,然后与“ jspUri ” 进行拼接,如图6-4  和图 6-5    所示
图6-4  赋值给变量 pathInfo 并拼接(一)

图 6-5  赋值给变量 pathInfo 并拼接(二)

        

         接下来调用 serviceJspFile()方法,如图 6-6 所示

图6-6  调用 serviceJspFile()方法

        首先生成 JspServletWrapper 对象,如图 6-7   所示
图 6-7 生成 JspServletWrapper 对象

 

        然后调用 JspServletWrapper.service() 方法,如图6-8   所示

图 6-8 调用 JspServletWrapper.service()方法

 

        获取对应的 servlet ,如图 6-9  所示。

图 6-9  获取对应的 servlet

 

调用该 servlet service 方法,如图 6-10  所示

 

图 6-10 调用的 service 方法

 

接下来解析上传文件中的 Java 代码。至此, RCE 漏洞原理分析完毕。调用链如下图所示
RCE 漏洞原理分析完毕

 


http://chatgpt.dhexx.cn/article/rH1dxQTA.shtml

相关文章

Tomcat HTTP协议与AJP协议

https://blog.csdn.net/jeikerxiao/article/details/82745516 Tomcat HTTP协议与AJP协议 HTTP Connector AJP Connector 配置 Tomcat在server.xml中配置了两种连接器。 HTTP Connector 拥有这个连接器&#xff0c;Tomcat才能成为一个web服务器&#xff0c;但还额外可处理Serv…

Tomcat架构解析之AJP

一、前言 除了HTTP&#xff0c;Tomcat还支持AJP协议&#xff0c;以便于Apache HTTP Server等Web服务器集成&#xff0c;这篇博客主要讲解AJP协议的基础知识以及其配置使用方式。 二、基础知识 为了满足负载均衡、静态资源优化、遗留系统集成&#xff08;如集成PHP Web应用&…

HTTP协议与AJP协议

AJP 全称 Apache JServ Protocol&#xff0c; 是定向包协议&#xff0c;因为性能的原因&#xff0c;使用二进制格式来传输可读性文本&#xff0c;WEB服务器通过TCP连接和SERVLET容器连接。 一旦WEB服务器打开了一个到SERVLET容器的连接&#xff0c;连接处于下面的状态&#xff…

解决Destroying ProtocolHandler [“ajp-apr-8009“]

今天刚开始调JSP网站还好好的&#xff0c;后来中间注销了电脑一次&#xff0c; 再打开调试它&#xff0c;就遇到了这个 无法启动服务器的问题&#xff1a; Destroying ProtocolHandler ["ajp-apr-8009"] 上网百度了下&#xff0c;说是端口号被占用了。 解决办法&…

你知道HTTP协议,但你了解AJP协议吗?

什么是AJP协议&#xff1f; AJP 协议用于web服务器和应用服务器之间的通信&#xff1f;为什么不用HTTP呢&#xff1f; Web服务器和应用服务器有什么区别&#xff1f; AJP协议和HTTP 协议有什么区别&#xff1f; 为什么客户端与服务器之间的通信使用HTTP协议而不是用AJP协议&…

WEB安全:Tomcat-Ajp协议漏洞分析

一、漏洞描述 Apache与Tomcat都是Apache开源组织开发的用于处理HTTP服务的项目,两者都是免费的,都可以做为独立的Web服务器运行。 Apache Tomcat服务器存在文件包含漏洞,攻击者可利用该漏洞读取或包含 Tomcat 上所有 webapp 目录下的任意文件,如:webapp 配置文件或源代码…

ajp 定向包协议 二进制代替文本提高性能 简介

AJP协议是定向包&#xff08;面向包&#xff09;协议&#xff0c;采用二进制形式代替文本形式&#xff0c;以提高性能。Web Server一般维持和Web Container的多个TCP Connecions&#xff0c;即TCP连接池&#xff0c;多个request/respons循环重用同一个Connection。但是当Connec…

Java高级自我介绍

先放个大招&#xff0c;哈哈&#xff0c;相信很多朋友准备了很久技术方面的内功&#xff0c;但是在真正与HR交锋的时候&#xff0c;有时还是败下阵来&#xff0c;究其原因之一&#xff0c;竟然是第一招错了&#xff0c;我自己也是&#xff0c;&#xff0c;所以&#xff0c;周末…

java开发自我介绍范文(合集)

java开发自我介绍范文3篇 java开发自我介绍范文篇一&#xff1a; Good morning ! It is really my honor to have this opportunity for a interview, I hope i can make a good performance today. Im confident that I cansucceed. Now i will introduce myself briefly I am…

Java面试中如何介绍自己的项目经验?

&#x1f447;&#x1f447;关注后回复 “进群” &#xff0c;拉你进程序员交流群&#x1f447;&#x1f447; 作者: hsm_computer 来源: https://www.cnblogs.com/JavaArchitect/p/7586949.html 在面试时&#xff0c;经过寒暄后&#xff0c;一般面试官会让介绍项目经验 。常见…

Java程序员面试时,如何进行自我介绍呢?

现在不管什么面试都会面对的一个环节&#xff0c;就是“自我介绍”。这个环节是很多企业作为选拔人才的一个方式与标准。那么&#xff0c;Java程序员面试自我介绍部分讲什么内容&#xff1f;小千给你详细解答下。 Java程序员自我介绍要有一条清晰的线索&#xff0c;便于组织自…

Java面试自我介绍怎么说?Java面试技巧!

自我介绍可谓是面试中最讨厌的环节了&#xff0c;许多程序员自身技术水平相当不错&#xff0c;但不善于表达&#xff0c;在自我介绍环节往往容易给面试官一个不好的印象。但这又是不可避免的&#xff0c;想要别人知道你是谁&#xff0c;你会什么&#xff0c;你做过什么&#xf…

JAVA面试技巧之自我介绍

【如何进行自我介绍】 自我介绍这个问题&#xff0c;不用多说了&#xff0c;面试必定会问&#xff01;如果想要在自我介绍的时候就能够打动面试官&#xff0c;吸引面试官对我们的兴趣&#xff0c;那么像我们这种接受过Java培训的程序员的自我介绍当然不能和应届生或者其他非技术…

AIOP简介

AIOP&#xff1a;AI for IT Operations

AIOps,让金融智能化运维化繁为简

前言 数字化转型是今天金融企业保持竞争力、拓展业务边界的必经之路。这让企业数据中心运维工作不得不面对海量数据压力的挑战。显然&#xff0c;传统运维方法已经无法满足企业数字化时代的新需求&#xff0c;构建面向未来的智能运维体系成为金融企业转型的关键。 2022年银保…

AIOps产品与架构浅析

【摘要】 本文简要介绍AIOps系统主要组成部分&#xff0c;介绍该系统在企业级IT运维场景下的作用和地位。 我们已经成功地应用了人工智能和机器学习来自动化传统的人工任务和IT操作过程。从异常检测到自动修复&#xff0c;现在将前沿算法融入到易于使用的工具中&#xff0c;允…

AIOps变革

图片摘自灵犀官网 目前稍微有点规模的公司都走到了2.0和3.0&#xff0c;之后4.0会逐渐普及 AIOps目前主要是应用数据发现故障&#xff0c;由于AI目前无法理解业务&#xff0c;所以很多故障处理依然需要依靠人工完成。深度的AI自动发现和故障处理需要智能AI组件的加入&#xf…

AIoT是什么?

AIoT是AI人工智能与IoT物联网的缩写&#xff0c;指的是人工智能物联网&#xff0c;即通过物联网收集来自不同维度的海量数据&#xff0c;存储于云端、边缘端&#xff0c;再根据大数据分析以及AI等技术&#xff0c;实现万物数据化、万物智联化。 谈到物联网&#xff0c;出现频率…

AIops相关算法

文章目录 根因分析清华FOCUS&#xff1a;找影响系统性能瓶颈的原因Adtributor&#xff1a;根因定位MSRA iDice&#xff1a;多维指标突变定位清华Hotspot&#xff1a;多维根因定位 智能变更清华FUNNEL&#xff1a;评估变更影响 异常检测雅虎EGADS&#xff1a;KPI异常检测框架清华…

智能运维AIOps,aiops对比传统运维工具的优势

在智能化、智能化时代&#xff0c;IT从手工制作到完全自动化&#xff0c;从传统的运维流程管理到智能化。“运维智能”这将是行业的发展趋势。  目前&#xff0c;许多用户机房选择传统运维模式、日常运维服务、检查维护工作需要手工记录和报告&#xff0c;检查质量难以保证&a…