Xiuno BBS 审计之问题02:后台用户搜索可能造成严重性能 DoS
贰先生 7小时前

问题:后台用户搜索将用户输入作为 LIKE/精确条件拼接进 SQL,依赖 addslashes 防注入

现象

后台 admin/route/user.php 的用户搜索接口将用户从 URL 接收的 $keyword 直接作为查询条件,通过 $cond[$srchtype] = $keyword 写入条件数组后交给 db_find()  db_cond_to_sqladd() 拼接 SQL。该流程最终仅靠 addslashes() 进行转义,未做参数预处理。在 GBK/多字节字符集场景下可被宽字节绕过;同时 LIKE 条件未对 %_ 进行转义,存在 LIKE 注入导致全表遍历和性能 DoS。

$srchtype 虽然做了 in_array($srchtype, $allowtype) 白名单校验,但 $keyword 本身未做任何字符校验,且 $srchtype 同样来自 param(2)(默认 htmlspecialchars),最终被用作列名拼接 `"$srchtype"`=...,若白名单逻辑被x插件修改可导致列名注入。

源码证据

文件:xiunobbs_4.0.4/admin/route/user.php 行 14-35(接收用户搜索关键词并写入 cond 数组)

$pagesize = 20;
$srchtype = param(2);
$keyword  = trim(xn_urldecode(param(3)));
$page     = param(4, 1);

$cond = array();
$allowtype = array('uid', 'username', 'email', 'gid', 'create_ip');

if($keyword) {
    !in_array($srchtype, $allowtype) AND $srchtype = 'uid';
    $cond[$srchtype] = $srchtype == 'create_ip' ? ip2long($keyword) : $keyword; 
}

$n = user_count($cond);
$userlist = user_find($cond, array('uid'=>-1), $page, $pagesize);
$pagination = pagination(url("user-list-$srchtype-".urlencode($keyword).'-{page}'), $n, $page, $pagesize);

文件:xiunobbs_4.0.4/xiunophp/db.func.php 行 242-279(条件拼接最终走 addslashes)

function db_cond_to_sqladd($cond) {
    $s = '';
    if(!empty($cond)) {
        $s = ' WHERE ';
        foreach($cond as $k=>$v) {
            if(!is_array($v)) {
                $v = (is_int($v) || is_float($v)) ? $v : "'".addslashes($v)."'";
                $s .= "`$k`=$v AND ";
            } elseif(isset($v[0])) {
                // ...
            } else {
                foreach($v as $k1=>$v1) {
                    if($k1 == 'LIKE') {
                        $k1 = ' LIKE ';
                        $v1="%$v1%";              // 未对 %、_ 转义
                    }
                    $v1 = (is_int($v1) || is_float($v1)) ? $v1 : "'".addslashes($v1)."'";
                    $s .= "`$k`$k1$v1 AND ";
                }
            }
        }
    }
    return $s;
}

文件:xiunobbs_4.0.4/route/thread.php 行 85 + 117(前台关键词搜索同样将 $keyword 传入 LIKE 条件)

$tid = param(1, 0);
$page = param(2, 1);
$keyword = param(3);
// ...
if($keyword) {
    $thread['subject'] = post_highlight_keyword($thread['subject'], $keyword);
    $keywordurl = "-$keyword";
}

文件:xiunobbs_4.0.4/model/thread.func.php 行 290-292(关键词搜索最终调用 db_find + LIKE 条件)

function thread_find_by_keyword($keyword) {
    $threadlist = db_find('thread', array('subject'=>array('LIKE'=>$keyword)), array(), 1, 60);
    // ...
}

文件:xiunobbs_4.0.4/admin/route/thread.php 行 64-66(后台主题扫描关键词同样未校验)

$userip = param('userip');
$cond['userip'] = $userip ? ip2long($userip) : 0;
$cond['keyword'] = param('keyword');

风险等级与结论

高危

危害后果:

  • 在 GBK 等多字节字符集环境下,$keyword 通过 addslashes 后仍可被宽字节绕过,导致后台 SQL 注入。后台注入因管理员权限高,可直接写马提权至服务器 RCE。
  • LIKE 查询未对 %_ 转义,攻击者可提交 % 触发全表 LIKE 扫描,对大表造成严重性能 DoS。
  • 列名 $srchtype 通过 `"$srchtype"` 直接拼接,白名单虽限制了 5 种字段,但任何对白名单的修改(如插件 hook)都会立即转为列名注入点。
  • 攻击面:后台接口需管理员登录,但配合 CSRF 缺陷(参见另案)可在管理员不知情的情况下被外部触发。

修复建议:

  1. 将所有 db_cond_to_sqladd 调用改为 PDO prepare() + bindValue(),参数化绑定彻底消除注入。
  2. LIKE 查询对 $keyword 中的 %_\ 调用 addcslashes($keyword, '%_\\') 转义,避免通配符注入。
  3. 列名 $srchtype 用严格的 switch-case 映射到固定字符串,禁止直接用用户输入做列名拼接。
  4. 强制 utf8mb4 字符集连接,关闭 PDO::ATTR_EMULATE_PREPARES,杜绝宽字节注入温床。
最后于 5小时前 被贰先生编辑 ,原因:
最新回复 (0)
全部楼主
返回