DeDeCMS(织梦 CMS)是一款国内比较专业的 PHP 网站内容管理系统,从 04 年发行至今,
已近七个年头,也经历了无数次的升级和改版,功能也不断增强。笔者原本以为这应该是一款安全性比较高的 CMS 系统,然而分析后令人感到 迷茫,迷茫国内比较专业的系统经历七年发展,其安全还是令人堪忧。或许网络原本就没有 绝对的安全。 注入漏洞 漏洞一:/member/ajax_membergroup.php 页面的 membergroup 变量没有过滤导致数字 型注入,关键代码如下: //编辑分组 elseif($action == 'post') { if(empty($membergroup)){ echo "您还没有设置分组!"; exit; } $sql = "UPDATE `dede_member_friends` SET `groupid`='{$membergroup}' WHERE `fid`='{$mid}' AND `mid`='{$cfg_ml->M_ID}';"; $dsql->ExecuteNoneQuery($sql); $row = $dsql->GetOne("SELECT groupname FROM dede_member_group WHERE mid = {$cfg_ml->M_ID} AND id={$membergroup}"); //数字型注入 echo " ".$row['groupname']." <a href='#' onclick='EditMemberGroup($mid);return false;'>修改</a>"; } 很明显当“action=post”时,$membergroup 导致数字型注入漏洞,但是 DeDeCMS 在访问 MySql 数据库之前,使用 CheckSql()自定义函数对 SQL 语句进行安全检查,无法直接注入。 绕 过 防 注 入 。 CheckSql() 函 数 定 义 在 /include/dedesql.class.php 或 /include/dedesqli.class.php 数据库类文件中,代码如下: if (!function_exists('CheckSql')) { function CheckSql($db_string,$querytype='select') {global $cfg_cookie_encode; $clean = '';$error='';$old_pos = 0;$pos = -1; ...(略) //如果是普通查询语句,直接过滤一些特殊语法 if($querytype=='select') {$notallow1= "[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1 ,}"; //[^0-9a-z@\._-]{1,}即至少 1 个非数字、小写字母、@等字符, if(preg_match("/".$notallow1."/", $db_string)) {//①preg_match 未使用参数 i,使用大写绕过,如:Union puts(fopen($log_file,'a+'),"$userIP||$getUrl||$db_string||SelectBreak\r\n") ; exit("<font size='5' color='red'>Safe Alert: Request Error step 1 !</font>"); } } while (TRUE) { $pos = strpos($db_string, '\'', $pos + 1); if ($pos === FALSE) {break; } //②假如字符串$db_string 中不存在“\'”退出 while 循环,存在则继续向下 执行 $clean .= substr($db_string, $old_pos, $pos - $old_pos); while (TRUE) { ...(略) } $clean .= '$s$'; //③将字符串$db_string 中"\'"和"\'"之间的字符转为"$s$",即信任之间的字 符串,绕过防注入的关键 $old_pos = $pos + 1; } …..(继续接如下代码) } } $clean .= substr($db_string, $old_pos); $clean = trim(strtolower(preg_replace(array('~\s+~s' ), array(' '), $clean))); //④"\s"匹配任何空白字符,包括空格、制表符、换页符等,$clean 转为小写 //⑤再次检查 union 关键字 if (strpos($clean, 'union') !== FALSE && preg_match('~(^|[^a-z])union($|[^[a-z])~s', $clean) != 0) { $fail = TRUE; $error="union detect"; } //⑥依次检查--、#、benchmark、load_file、outfile、select 等关键字 elseif (strpos($clean, '/*') > 2 || strpos($clean, '--') !== FALSE || strpos($clean, '#') !== FALSE) {...(略) } //这些函数不会被使用,但是黑客会用它来操作文件,down 掉数据库 |