CVE-2018-20129 织梦V5.7 SP2前台鸡肋文件上传getshell

抱大佬大腿的第一天,今日要做的事情是复现下CVE-2018-20129,也就是DedeCMS V5.7SP2 的一处通过文件上传get shell

介绍

此漏洞限制很大。

  • 需要管理员权限
  • 需要开启会员功能
    也就是说虽然是前台getshell但是需要有后台权限

详情

漏洞产生于/include/dialog/select_images_post.php

1
2
require_once(dirname(__FILE__)."/config.php");
require_once(dirname(__FILE__)."/../image.func.php");

看下config.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//检验用户登录状态
$cuserLogin = new userLogin();

if($cuserLogin->getUserID() <=0 )
{
if(empty($adminDirHand))
{
ShowMsg("<b>提示:需输入后台管理目录才能登录</b><br /><form>请输入后台管理目录名:<input type='hidden' name='gotopage' value='".urlencode($dedeNowurl)."' /><input type='text' name='adminDirHand' value='dede' style='width:120px;' /><input style='width:80px;' type='submit' name='sbt' value='转入登录' /></form>", "javascript:;");
exit();
}
$adminDirHand = HtmlReplace($adminDirHand, 1);
$gurl = "../../{$adminDirHand}/login.php?gotopage=".urlencode($dedeNowurl);
echo "<script language='javascript'>location='$gurl';</script>";
exit();
}

会先检验用户登录状态,必须要是后台管理员

同时config.php

1
require_once(dirname(__FILE__)."/../common.inc.php");

而common.inc.php

1
2
3
4
5
//转换上传的文件相关的变量及安全处理、并引用前台通用的上传函数
if($_FILES)
{
require_once(DEDEINC.'/uploadsafe.inc.php');
}

uploadsafe.inc.php中含有用来处理文件相关的函数

1
2
3
4
5
6
7
8
9
10
$cfg_not_allowall = "php|pl|cgi|asp|aspx|jsp|php3|shtm|shtml";
......
......
if(!empty(${$_key.'_name'}) && (preg_match("#\.(".$cfg_not_allowall.")$#i",${$_key.'_name'}) || !preg_match("#\.#", ${$_key.'_name'})) )
{
if(!defined('DEDEADMIN'))
{
exit('Not Admin Upload filetype not allow !');
}
}

上传的文件的后缀名不能是$cfg_not_allowall中的这些


1
2
3
4
5
6
$imgfile_name = trim(preg_replace("#[ \r\n\t\*\%\\\/\?><\|\":]{1,}#", '', $imgfile_name));
if(!preg_match("#\.(".$cfg_imgtype.")#i", $imgfile_name))
{
ShowMsg("你所上传的图片类型不在许可列表,请更改系统对扩展名限定的配置!", "-1");
exit();
}

这段代码表示$imgfile_name的一些特殊符号会先被去掉,在限制了php的情况下可以使用p?hp之类的后缀进行绕过,并且$imgfile_name中必须有.jpg,.png之类的


1
2
3
4
5
6
7
$sparr = Array("image/pjpeg", "image/jpeg", "image/gif", "image/png", "image/xpng", "image/wbmp");
$imgfile_type = strtolower(trim($imgfile_type));
if(!in_array($imgfile_type, $sparr))
{
ShowMsg("上传的图片格式错误,请使用JPEG、GIF、PNG、WBMP格式的其中一种!","-1");
exit();
}

这段代码表示Content-Type必须是$sparr中的类型


  • 如果网站配置AddType application/x-httpd-php .phtml之类的可以采用.phtml绕过后缀名限制
  • 因为? *<* > 等字符会被过滤,所以也可以以使用.p?hp的形式绕过

复现

首先在后台打开会员功能,同时把注册审核给关了,方便注册

然后注册一个新账号,进入发表文章界面

点击下方的按钮后选择上传

修改后缀名为a.gif.p?hp,同时讲图片内容中加上**

进行访问

修复

  • 关闭会员功能
  • 采用白名单
  • 改进扩展名判断