环境
windows 11
phpstudy
easycms 7.7.4
代码分析
-
漏洞点:文件
lib/admin/database_admin.php
中的函数dorestore_action()
方法。//还原数据
function dorestore_action() {
/* $db_dir = explode('_',front::get('db_dir'));
if($db_dir[2]!=_VERCODE){
front::flash(lang_admin('database_recovery_failed').'!');
front::redirect(url::create('database/baker'));
}*/
$dir=ROOT.'/data/backup-data/'.front::get('db_dir');
if(is_dir($dir)) {
$db_files=front::scan($dir);
foreach($db_files as $db_file) {
if(!preg_match('/^./',$db_file)) tdatabase::getInstance()->restoreTables($dir.'/'.$db_file);
}
//更新表
$nerrCode=service::checktable();
if ($nerrCode) {
$this->json_info(5, $nerrCode);
exit;
}
user::deletesession();
category::deletesession();
type::deletesession();
special::deletesession();
front::flash(lang_admin('database_recovery').lang_admin('success').'!');
}
front::redirect(url::create('database/baker'));
}看到该方法运行中会直接接受GET参数
db_dir
拼接成目录$dir=ROOT.'/data/backup-data/'.front::get('db_dir');
没有经过过滤,该目录可以进行伪造。 -
之后执行
$db_files=front::scan($dir);
获取该目录下得文件名,并带入方法tdatabase::getInstance()->restoreTables()
执行下一步操作。 -
跟进
restoreTables()
方法,在文件lib/table/tdatabase.php
中。function restoreTables($file)
{
$database=config::getdatabase('database');
set_time_limit(0);
//$database = new tdatabase();
$sqlquery = file_get_contents($file);
if (!$sqlquery)
return;
$sqlquery = str_replace("r", "", $sqlquery);
$sqlquery = str_replace("cmseasy_", $database['prefix'] , $sqlquery);
$sqls = preg_split ("/;(--)+[ t]{0,}n/", $sqlquery);
//var_dump($sqls);exit;
$nerrCode = "";
$i = 0;
foreach ($sqls as $q) {
$q = trim($q);
if ($q == "") {
continue;
}
if ($this->query($q))
$i++;
else
$nerrCode .= "执行:<font color='blue'>$q</font> 出错!</font><br>";
}
return $nerrCode;
}可以看到,
$sqlquery = file_get_contents($file);
将文件读取并赋值给sqlquery
,在经过一系列的替换和切割后,形成sql语句数组$sqls
,并遍历带入$this->query()
方法执行数据库操作。 -
由此可以得到,如果能够控制某文件内容,将目录传递给
dorestore_action()
方法,即可实现sql语句的执行。 -
测试头像上传功能,上传内容为sql语句的图片。定位代码在
lib/default/tool_act.php
的uploadimage3_action()
方法。可以看到将上传的图片内容传递到
front::checkstr()
方法进行检查,跟进lib/tool/front_class.php
文件的checkstr()
方法static function checkstr($str)
{
if (preg_match("/<(/?)(script|i?frame|style|html|?php|body|title|link|meta)([^>]*?)>/is", $str, $match)) {
//front::flash(print_r($match,true));
return false;
}
if (preg_match("/(<[^>]*)on[a-zA-Z]+s*=([^>]*>)/is", $str, $match)) {
return false;
}
return true;
}对文件内容进行两次关键词匹配,可以看到没有对sql语句的关键词进行匹配,可以上传内容为sql语句的图片。
演示验证
-
通过头像上传包含payload的图片
-
访问连接
http://easy.test/index.php?case=database&act=dorestore&admin_dir=admin&db_dir=../../cn/upload/images/202111
提取出相关图片
-
-
提取出构造的sql语句
-
执行成功,页面出现报错信息。
修复建议
1.更新到最新版本
2.对路径进行关键词过滤,例如"../"等
原文始发于微信公众号(无级安全):easycms 7.7.4 后台sql注入漏洞复现
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论