嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

前言

2020 年 1 月 6 日,國家信息安全漏洞共享平臺(CNVD)收錄了由北京長亭科技有限公司發現並報送的 Apache Tomcat 文件包含漏洞。Tomcat AJP 協議由於存在實現缺陷導致相關參數可控,攻擊者利用該漏洞可通過構造特定參數,讀取服務器 webapp 下的任意文件。若服務器端同時存在文件上傳功能,攻擊者可進一步實現遠程代碼的執行。

Tomcat AJP 協議的這種實現缺陷,對於 SpringBoot 開發的 web 應用是否受影響了?且聽筆者一一道來。

AJP 協議

根據 apache 官網 AJP 協議相關介紹:

The original document was written by Dan Milstein, [email protected] on December 2000.

Overview of the protocol

The ajp13 protocol is packet-oriented. A binary format was presumably chosen over the more readable plain text for reasons of performance. The web server communicates with the servlet container over TCP connections. To cut down on the expensive process of socket creation, the web server will attempt to maintain persistent TCP connections to the servlet container, and to reuse a connection for multiple request/response cycles.

Once a connection is assigned to a particular request, it will not be used for any others until the request-handling cycle has terminated. In other words, requests are not multiplexed over connections. This makes for much simpler code at either end of the connection, although it does cause more connections to be open at once.

AJP13 協議全稱為 Apache JServ Protocol version 1.3 ,最初由 Dan Milstein 於2000年12月發表,後被 Apache 軟件基金會 Jakarta 項目採納。

AJP13 是一種二進制 TCP 傳輸協議,通過在網絡傳輸二進制包(packet)來完成 Tomcat 與 http 服務器的請求與響應,顯然這種方式比純文本(如 text、xml等)傳輸的 http 協議效率要高的多。

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

但是 AJP13 協議對瀏覽器支持不夠好,由於其定位是 “ Tomcat 與 HTTP 服務器之間通信的協議”,這或許是 http 協議比較盛行的原因吧。

說完了 Tomcat AJP13 協議的來龍去脈接著,進入主題。

SpringBoot 為什麼這麼火?

spring-boot-starter-web

對 Spring 比較熟悉的話, 基於 SpringBoot 開發 web 應用時,引入 spring-boot-starter-web 組件是必不可少的,spring-boot-starter-web 的職責是負責 web 應用的啟動 、初始化、運行和停止。而 spring-boot-starter-web 組件之所以能夠跑起來,少不了 http 協議的支持,典型代表就是 tomcat 服務器。

通過翻閱 spring-boot-starter-web 組件的相關 maven 依賴,我們找到了 spring-boot-starter-tomcat 組件。

<code><dependency>
  <groupid>org.springframework.boot/<groupid>
   <artifactid>spring-boot-starter-tomcat/<artifactid>
  <version>2.1.5.RELEASE/<version>
  <scope>compile/<scope>
/<dependency>/<code>

接著查找 spring-boot-starter-tomcat 的 maven 依賴, 其引入了 tomcat-embed-core 、tomcat-embed-el 、tomcat-annotations-api 等嵌入式組件。

<code><dependency>
<groupid>javax.annotation/<groupid>
<artifactid>javax.annotation-api/<artifactid>
<version>1.3.2/<version>
<scope>compile/<scope>
/<dependency>
<dependency>
<groupid>org.apache.tomcat.embed/<groupid>
<artifactid>tomcat-embed-core/<artifactid>
<version>9.0.19/<version>
<scope>compile/<scope>
<exclusions>
<exclusion>
<artifactid>tomcat-annotations-api/<artifactid>
<groupid>org.apache.tomcat/<groupid>
/<exclusion>
/<exclusions>
/<dependency>
<dependency>
<groupid>org.apache.tomcat.embed/<groupid>
<artifactid>tomcat-embed-el/<artifactid>
<version>9.0.19/<version>
<scope>compile/<scope>
/<dependency>
<dependency>
<groupid>org.apache.tomcat.embed/<groupid>
<artifactid>tomcat-embed-websocket/<artifactid>
<version>9.0.19/<version>
<scope>compile/<scope>
/<dependency>
/<code>

正是由於這些嵌入式組件的加入,免去了 Tomcat 單獨安裝部署的繁雜步驟,我想這也是 SpringBoot 非常火的原因之一吧。

SpringBoot 對 AJP 協議的支持

通過閱讀 tomcat-embed-core 組件,說明嵌入式 tomcat 是支持 AJP 協議的,相關代碼在 org.apache.coyote.ajp 目錄下。

但是奇怪的是,在 SpringBoot 的 yml 文件配置中,並沒有找到 ajp 協議相關的 server 參數配置。

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

筆者猜測,雖然 Tomcat 集成了 ajp 協議,但是不推薦使用吧。但是有沒有辦法支持 ajp 協議了,答案是可以的,具體代碼如下:

<code>@Configuration
public class AJPConfig {

private static final String PROTOCOL = "AJP/1.3";

@Value("${tomcat.ajp.port:8009}")
private int ajpPort;

@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
Connector ajpConnector = new Connector();
ajpConnector.setProtocol(PROTOCOL);
ajpConnector.setPort(ajpPort);

tomcat.addAdditionalTomcatConnectors(ajpConnector);
return tomcat;
}

}/<code>

筆者上述配置需要依賴 SpringBoot 1.x 環境。

AjpProcessor

如果對 tomcat 架構比較瞭解的話,tomcat 大部分請求與響應由協議(Protocol)中的處理器(Processor)完成的。

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

所以在 tomcat 服務器接收 ajp 請求時, 由 AjpProcessor 來處理 ajp 真實的 request 請求消息。

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

然後,通過 prepareRequest 方法將 ajp 請求內容取出來,設置成 request 對象的 Attribute 屬性

嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響


嵌入式 Tomcat AJP 協議對 SpringBoot 應用的影響

因此,黑客通過設置 request_uri、path_info 、servlet_path 屬性值,從而可以讀取到 /WEB-INF 下面的所有敏感文件,不限於class、xml、jar等文件。

<code>javax.servlet.include.request_uri
javax.servlet.include.path_info
javax.servlet.include.servlet_path/<code>

至於漏洞的詳細分析不是本文重點,傳送門:

https://blog.csdn.net/u012206617/article/details/104416626/


分享到:


相關文章: