DedeCMS RCE漏洞分析

前言

​ 最近看到几个公众号都披露了DedeCMS的漏洞,很久也没有分析过PHP的漏洞了,趁着周末没什么事情分析下这两个漏洞。

V5.8.1内测版前台RCE

​ 这个漏洞在这篇文章有过分析,但我还是决定自己搭建好环境分析一下,以便自己能理解的更加深刻。

分析过程

​ 在DedeCMS中,当访问出现某些异常,Dede会弹出一个窗口给用户提示。

image-20211010175426875

​ 而这个页面的生成和处理主要是由ShowMsg方法完成的。生成的页面包含一个跳转地址,如果这个地址在函数调用时设置为-1,则会去接收Referer头中的地址。

image-20211010175536974

​ 将Referer中接收的内容放到msg中,并通过Dede的模板渲染。

1
2
3
4
5
6
7
8
9
10
11
12
13
    $func .= "var pgo=0;
function JumpUrl(){
if(pgo==0){ location='$gourl'; pgo=1; }
}\r\n";
$rmsg = $func;
...
}
$msg = $htmlhead . $rmsg . $htmlfoot;
}

$tpl = new DedeTemplate();
$tpl->LoadString($msg);
$tpl->Display();

​ 在Display函数中,通过WriteCache将内容写入到缓存文件并进行文件包含。

1
2
3
4
5
6
7
public function Display()
{
global $gtmpfile;
extract($GLOBALS, EXTR_SKIP);
$this->WriteCache();
include $this->cacheFile;
}

image-20211010181536464

​ 虽然看上去可以直接命令执行,但是我们注意到在写入缓存前会先调用CheckDisabledFunctions检查Disablefunction, 这里检查了常见的敏感函数,但是我们仔细分析会发现这里其实只是检查了敏感的字符串,我们可以直接利用反引号命令执行。

image-20211010181956866

image-20211010182203874

漏洞总结

是否有其他点可以造成漏洞?

​ 虽然看网上的文章是利用了flink.php这个文件来进行利用的,可了解漏洞原理后会发现,只要是调用了ShowMsg函数并且第二个参数为-1的都有可能导致这个漏洞。而似乎能够未授权访问的都在plus目录下,所以只要在这个目录下找都是可以无限制RCE的。

​ 比如在search.php中,当keyword包含一些敏感字符串或者字符长度小于2时,也会导致这个漏洞。

image-20211010210420074

​ 再仔细分析一下,其实也不是只有在ShowMsg中才能造成漏洞,只要在加载模板的过程中通过LoadString加载,并且$msg的内容可控就可以了。

1
2
3
$tpl = new DedeTemplate();
$tpl->LoadString($msg);
$tpl->Display();

​ 但是除了ShowMsg直接调用了LoadString只有在SetString中调用了,而SetString并没有任何调用。

image-20211010210805011

​ 还有一种可能也可以导致漏洞,就是如果Showmsg函数中的msggourl的值可控也可以导致漏洞。

​ 比如在user-do.php中,当用户名不合法时,我们输入的用户名会被带入到ShowMsg的参数中。

image-20211010214456729

​ 也有些文件第二个参数可控也可以造成漏洞。

image-20211010214852158

其他版本是否受影响

​ 下载DedeCMS 5.7.7版本测试,在Showmsg中并不会接收refere头中的信息,所以此处无法利用。

image-20211010212232293

​ 但前面分析过也可以通过控制msg或者gourl参数来利用,仅仅从上面来看不能说一定没有,主要还是看下面,在这个版本的Dedecms中,获得msg后直接通过echo输出,并没有通过模板渲染所以从根源上就不会出现上面的问题了。

image-20211010215213408

并且在Display函数中也是直接输出解析模板,没有文件包含操作。

image-20211010215558125

​ 下载最新的5.8.0版本和5.7.7 版本一样,都没有使用模板处理,所以也不会导致漏洞。