Xiuno BBS 审计之问题:插件安装直接 include 可 RCE
贰先生 5小时前

此文章为XIUNOX版本重构审计时发现问题,XIUNOX版本已优化修复此问题。分享出来方便后续想基于xiuno bbs4.0.4版本制作维护版本或插件模板等需求的开发者和站长参考。

现象

Xiuno BBS 4.0.4 安装、卸载、升级、设置插件时,会直接 include _include(APP_PATH."plugin/$dir/install.php") 等插件自带脚本,且没有任何沙盒、签名校验、函数黑名单。插件作者可以在 install.php 中植入任意代码:删库、写马、读取 conf.php 中的数据库密码、向远程发送站点密钥。即便禁用插件,install.php 已经执行过一次,后门已落地。

源码证据

文件:xiunobbs_4.0.4/admin/route/plugin.php 第 155-175 行(安装时 include install.php)

} elseif($action == 'install') {
    plugin_lock_start();
    $dir = param_word(2);
    plugin_check_exists($dir);
    $name = $plugins[$dir]['name'];

    // 插件依赖检查 / check plugin dependency
    plugin_check_dependency($dir, 'install');

    // 安装插件 / install plugin
    plugin_install($dir);

    $installfile = APP_PATH."plugin/$dir/install.php";
    if(is_file($installfile)) {
        include _include($installfile);              // 直接 include 插件提供的 PHP,无沙盒
    }
    plugin_lock_end();
    // ...
}

文件:xiunobbs_4.0.4/admin/route/plugin.php 第 203-223 行(卸载时 include unstall.php)

} elseif($action == 'unstall') {
    // ...
    plugin_unstall($dir);

    $unstallfile = APP_PATH."plugin/$dir/unstall.php";
    if(is_file($unstallfile)) {
        include _include($unstallfile);              // 同样无任何校验
    }
    // ...
}

文件:xiunobbs_4.0.4/admin/route/plugin.php 第 277-310 行(升级时 include upgrade.php)

} elseif($action == 'upgrade') {
    // ...
    plugin_install($dir);

    $upgradefile = APP_PATH."plugin/$dir/upgrade.php";
    if(is_file($upgradefile)) {
        include _include($upgradefile);              // 升级脚本任意执行
    }
    // ...
}

文件:xiunobbs_4.0.4/admin/route/plugin.php 第 317-324 行(设置页 include setting.php)

} elseif($action == 'setting') {
    $dir = param_word(2);
    plugin_check_exists($dir);
    $name = $plugins[$dir]['name'];

    include _include(APP_PATH."plugin/$dir/setting.php");   // 设置页任意 PHP 执行
}

文件:xiunobbs_4.0.4/admin/route/plugin.php 第 388-434 行(plugin_download_unzip 直接解压到 plugin/ 目录,无签名)

function plugin_download_unzip($dir) {
    global $conf;
    // ...
    $url = PLUGIN_OFFICIAL_URL."plugin-download-$dir-$siteid-$app_url.htm";
    $s = http_get($url);
    // ...
    $zipfile = $conf['tmp_path'].'plugin_'.$dir.'.zip';
    $destpath = APP_PATH."plugin/";
    file_put_contents($zipfile, $s);

    // 清理原来的钩子,防止叠加。
    rmdir_recusive(APP_PATH."plugin/$dir/hook/", 1);
    rmdir_recusive(APP_PATH."plugin/$dir/overwrite/", 1);

    // 直接覆盖原来的 plugin 目录下的插件目录
    xn_unzip($zipfile, $destpath);                  // 解压即落地,install.php 即可被 include
    // ...
}

风险等级与结论

风险等级:严重(Critical)|生态缺陷

危害:

  1. 安装任意插件 = 执行任意 PHP,无沙盒、无签名、无函数黑名单。
  2. install.php 可读取 conf/conf.php 中的 DB 密码、auth_key,外传给攻击者。
  3. install.php 可写文件到 upload/tmp/view/,植入持久化 webshell。
  4. 官 方源 plugin.xiuno.com 已失效(见独立缺陷),用户被迫从第三方下载,供应链攻击面巨大。
  5. 即便用户事后禁用、卸载插件,install.php 已执行过的副作用(删表、改密码、写马)无法回滚。

修复建议:

  • 引入插件签名机制:插件包必须附 conf.json.sig(Ed25519),plugin_download_unzip 解压后立即校验签名,不匹配则拒绝安装。
  • install/unstall/upgrade/setting.php 在受限沙盒中执行:禁用 exec/system/eval/file_put_contents/unlink/mysql_query 等危险函数(通过 disable_functions ini 临时注入)。
  • 限制 install.php 只能调用 BBS 提供的 plugin_install_hook() API 完成数据库变更,禁止直接 SQL。
  • 安装前展示 install.php 源码摘要给管理员审阅,并扫描危险关键字(evalexecfile_put_contentsfopenmysql$_POST$_GETbase64_decode)。
  • 强制 install.php 通过 _include() 编译时附加 <?php exit; 前缀防直接访问,但执行前去除(已有此机制,但仅对 hook 生效,install.php 未应用)。
最新回复 (0)
全部楼主
返回