DedeCMS v5.8.1_beta does not authorize remote command execution vulnerability analysis

0x00 Background

Dedecms'unauthorized RCE vulnerability notice was sent a few days before convincing the Public. The address is this: DedeCMS does not authorize remote command execution vulnerabilities

Look at the description.

Scope of impact: Formal: < v5.7.8 (SQL injection only), Internal beta: = v5.8.1_beta

This push seems to have been updated. The parentheses'(SQL injection only)'I didn't see before, if I remember correctly.

Since poc was not given and there were no relevant details available on the Internet, take a closer look at the description below.

The vulnerability is due to a variable override vulnerability in DedeCMS that allows an attacker to construct malicious code with template file inclusion without authorization to cause remote command execution attacks and ultimately gain the highest privileges on the server.

The cause is variable override, which is then used for malicious operations.

0x01 audit code

This is the address of dedecms in github:

In the release tag, we found 6.8.1 beta to download.

Since it is variable override, there are several places you can find using the IDE search keyword'$$':

  • dede/module_make.php
  • inclue/

dede is the directory behind the administrator's desktop, not necessarily. For inclue/, the main code is as follows:

    function CheckRequest(&$val)
        if (is_array($val)) {
            foreach ($val as $_k => $_v) {
                if ($_k == 'nvarname') {

        } else {
            if (strlen($val) > 0 && preg_match('#^(cfg_|GLOBALS|_GET|_POST|_COOKIE|_SESSION)#', $val)) {
                exit('Request var not allow!');


    foreach (array('_GET', '_POST', '_COOKIE') as $_request) {
        foreach ($$_request as $_k => $_v) {
            if ($_k == 'nvarname') {
                ${$_k} = $_v;
            } else {
                ${$_k} = _RunMagicQuotes($_v);


You can see that the main function is to convert the variables in the user's request, but here's a CheckRequest function that doesn't know if it's secured.

Although there is variable coverage here, there is a headache. This file is contained by almost all control routes. Where is the trigger point?..... Or equivalent to looking for a needle in a haystack.

That is, it is difficult to find the hole accurately by the content of this bug announcement alone.

dedecms has an address in github, so what's better if he updates it?

I thought so at first, but at a glance...... More than 2,000 files have been updated.... Basically all files have been updated, just in case you find something... a good routine...

OC Find by 0x02 Friend

This is the main content of flink.php.

if ($dopost == 'save') {
    $validate = isset($validate) ? strtolower(trim($validate)) : '';
    $svali = GetCkVdValue();
    if ($validate == '' || $validate != $svali) {
        ShowMsg('The verification code is incorrect!', '-1');
    $msg = RemoveXSS(dede_htmlspecialchars($msg));
    $email = RemoveXSS(dede_htmlspecialchars($email));
    $webname = RemoveXSS(dede_htmlspecialchars($webname));
    $url = RemoveXSS(dede_htmlspecialchars($url));
    $logo = RemoveXSS(dede_htmlspecialchars($logo));
    $typeid = intval($typeid);
    $dtime = time();
    $query = "INSERT INTO `#@__flink`(sortrank,url,webname,logo,msg,email,typeid,dtime,ischeck)
    ShowMsg('Successfully added a link, but auditing is required before it can be displayed!', '-1', 1);

After a brief look, the key function, ShowMsg, is locked. Located in include/common.func.php file.

Looking at the POC output point,

if (preg_match('/close::/', $gourl)) {
    $tgobj = trim(preg_replace('/close::/', '', $gourl));
    $gourl = 'javascript:;';
    $func .= "window.parent.document.getElementById('{$tgobj}').style.display='none';\r\n";

$func .= "var pgo=0;
function JumpUrl(){
if(pgo==0){ location='$gourl'; pgo=1; }
$rmsg = $func;
$rmsg .= "document.write(\"<div style='height:130px;font-size:10pt;background:#ffffff'><br />\");\r\n";
$rmsg .= "document.write(\"" . str_replace("\"", """, $msg) . "\");\r\n";
$rmsg .= "document.write(\"";

This variable is user controlled.

So...... Where does the variable cover... nothing....

0x03 Official Repair

The assignment of $gourl was deleted. Template rendering is removed and echo is replaced.

I was curious about the extent of the hole, downloaded the 5.7 source code, and found that there was no problem, affecting only v5.8.1_ Bea, there is quite an official meaning of poisoning, recalling today's official announcement of Zhimeng, "Notice about Reminder for Commercial Use Authorization of DEDECMS Products".

When you think it over, you will feel horrible.

0x04 from point to surface, trying to find other vulnerabilities

Start with showmsg

Go back to ShowMsg to trigger that, that is, LoadString is a dangerous function when $msg is controllable in the following code.

$tpl = new DedeTemplate();



Enter LoadString and find that the variable $str is assigned to sourceString.

    public function LoadString($str = '')
        $this->sourceString = $str;
        $hashcode = md5($this->sourceString);
        $this->cacheFile = $this->cacheDir . "/string_" . $hashcode . ".inc";
        $this->configFile = $this->cacheDir . "/string_" . $hashcode . "";

Find the sourceString assignment through the IDE.

No results.

Start with the project as a whole

The plus directory is accessible externally without logging in. Audit one by one.

Some problems have been found, but limited use has been made.

Background shell, /plus/ad_js.php Include File

Take it out of the database and write a file.

If you can get in the background, you can use it here.

0x05 Last

The code for this project is messy and worthless, except there are many domestic sites. The processing of that template can be delved into and seems a bit cumbersome. Let's start with that.

Posted by Deanznet on Thu, 11 Nov 2021 08:44:21 -0800