引言
Xiuno BBS 是一款轻量级、高性能的开源论坛系统,基于 PHP 7 和 MySQL 开发,采用 MVC + AOP 架构,支持灵活的插件机制和多种缓存技术(如 XCache、Redis)。其设计注重速度与效率,核心代码精简,压缩后仅约 1MB,响应时间可低至 0.01 秒,适用于高负载场景。系统以 MIT 协议开源,支持二次开发和商用,但在 2020 年因维护问题停止官方更新,源码仍可在 GitHub 获取。
本次代码审计针对 Xiuno BBS 4.0.4 版本,旨在识别潜在的安全漏洞、代码质量问题及性能瓶颈。审计范围涵盖核心模块、插件接口、数据库交互及文件上传功能,采用静态分析、动态测试和漏洞复现等方法,基于 2025 年 9 月 27 日的安全标准。报告将分析已知漏洞(如 CVE-2020-21493、CVE-2020-21494、CVE-2018-15559、CVE-2020-19914)并提出修复建议,为开发者提供安全性和稳定性优化的参考。
安装
-
获取源码
bash#这边添加github的加速 git clone https://gh-proxy.com/github.com/wanghaiwei/xiuno-docker.git #解压 unzip xiunobbs-4.0.4.zip -d xiuno #创建环境变量 mv .env.example .env
-
修改php的镜像文件php-fpm/Dockerfile
vbnetFROM php:fpm=>FROM php:7.3-fpm php:php:7.3-fpm
-
修改nginx的镜像文件nginx/Dockerfile
iniFROM nginx:latest=>>FROM nginx:1.29-perl
-
修改mysql的镜像文件mysql/Dockerfile
iniFROM mysql:5.7=>FROM mysql:5.7.24
-
修改网络配置
iniDOCKER_NET=10.10.0.1/16 => DOCKER_NET=10.10.0.0/1610.10.0.0/16
-
创建docker
docker compose up -d
192.168.244.149:8018
初始化系统
-
浏览器打开地址,默认端口是8018,选择语言,默认即可,点击下一步
-
点击同意协议
-
环境检查,点击下一步
-
选择InnoDB,数据库的服务器、用户名和密码分别填写.env里面对应的
MYSQL_SERVER_ADDRESS
、MYSQL_USER
、MYSQL_PASSWORD
,点击下一步 -
安装成功,并点击确认
-
到此可以正常使用了。
漏洞复现
CVE-2020-21493
访问控制错误漏洞,允许对用户名进行检索。
- 代码:
route\user.php line 67-82;
php
include _include(APP_PATH.'view/htm/user_login.htm');
} else if($method == 'POST') {
// hook user_login_post_start.php
$email = param('email'); // 邮箱或者手机号 / email or mobile
$password = param('password');
empty($email) AND message('email', lang('email_is_empty'));
if(is_email($email, $err)) {
$_user = user_read_by_email($email);
empty($_user) AND message('email', lang('email_not_exists'));
} else {
$_user = user_read_by_username($email);
empty($_user) AND message('email', lang('username_not_exists'));
}
lang\zh-cn\bbs.php line 120;
ini
'username_not_exists' => '用户名不存在',
-
请求报文:
request:
makefile
POST /?user-login.htm HTTP/1.1
Host: 192.168.1.5
Content-Length: 54
Accept: text/plain, */*; q=0.01
Origin: http://127.0.0.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3941.4 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://127.0.0.1/?user-login.htm
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: bbs_sid=c0ku6ujq1411p9fqbf9vvdricn
Connection: close
email=test&password=4297f44b13955235245b2497399d7a93
Response:
yaml
HTTP/1.1 200 OK
Date: Thu, 05 Dec 2019 14:51:29 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9
X-Powered-By: PHP/7.2.1
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 60
{
"code": "email",
"message": "用户名不存在"
}
-
页面效果
CVE-2020-21494
此漏洞为在初始化系统的时候,不会自动吧install里面的内容删掉,需要手动删除,如果忘记删除,则install/index.php还会存在,攻击者可利用该漏洞导致系统重装。
下面显示,已初始化完的系统,还是能进入安装向导页面。

CVE-2018-15559
存储跨站脚本攻击(XSS)漏洞
route\thread.php 第52-53行;
php
$message = param('message', '', FALSE);
empty($message) AND message('message', lang('please_input_message'));
$doctype = param('doctype', 0);
$doctype > 10 AND message(-1, lang('doc_type_not_supported'));
xn_strlen($message) > 2028000 AND message('message', lang('message_too_long'));
xiunophp\misc.func.php 第201-209行;
ini
// txt 转换到 html
function xn_txt_to_html($s) {
$s = htmlspecialchars($s);
$s = str_replace(" ", ' ', $s);
$s = str_replace("\t", ' ', $s);
$s = str_replace("\r\n", "\n", $s);
$s = str_replace("\n", '<br>', $s);
return $s;
}
model\post.func.php 第360-361行,doctype = 0(HTML)且 gid = 1(管理员): message_fmt = 原文(不做 htmlspecialchars)
bash
$arr['doctype'] == 0 && $arr['message_fmt'] = ($gid == 1 ? $arr['message'] : xn_html_safe($arr['message']));
$arr['doctype'] == 1 && $arr['message_fmt'] = xn_txt_to_html($arr['message']);
install\install.sql 第158行;
arduino
doctype tinyint(3) NOT NULL default '0', # 类型,0: html, 1: txt; 2: markdown; 3: ubb
doctype默认为1,构造数据包修改为0,然后打开帖子内容页面便能触发payload。


**注意:**这边管理员权限才有注入的权限,如果是普通会员则不行。
CVE-2020-19914
xiunobbs 4.0.4 中的跨站脚本 (XSS) 漏洞允许远程攻击者通过附件上传功能执行任意 Web 脚本或 HTML。
上传完后,通过Burp Suite
拦截记录如下:
上传html文件:

上传php文件

代码分析:
route\attach.php
的34行:
ini
$ext = file_ext($name, 7);
$filetypes = include APP_PATH.'conf/attach.conf.php';
!in_array($ext, $filetypes['all']) AND $ext = '_'.$ext;
$tmpanme = $uid.'_'.xn_rand(15).'.'.$ext;
$tmpfile = $conf['upload_path'].'tmp/'.$tmpanme;
$tmpurl = $conf['upload_url'].'tmp/'.$tmpanme;
conf/attach.conf.php
,这是不该后缀的文件,不在里面的后缀都会增加_
php
<?php
return array (
'all'=> array('av','wmv','wav','wma','avi','rm','rmvb','mp4', 'mp3','exe','bin','swf','fla','as','gif','jpg','jpeg','png','bmp','doc','xls','ppt','docx','xlsx','pptx','pdf',
'c','cpp','cc', 'txt','tar','zip','gz','rar','7z','bz','chm','bt','torrent','ttf','font','fon'
),
'video' => array('av','wmv','wav','wma','avi','rm','rmvb','mp4'),
'music' => array('mp3','mp4'),
'exe' => array('exe','bin'),
'flash' => array('swf','fla','as'),
'image' => array('gif','jpg','jpeg','png','bmp'),
'office' => array('doc','xls','ppt','docx','xlsx','pptx'),
'pdf' => array('pdf'),
'text' => array('c','cpp','cc', 'txt'),
'zip' => array('tar','zip','gz','rar','7z','bz'),
'book' => array('chm'),
'torrent' => array('bt','torrent'),
'font' => array('ttf','font','fon'),
'other' => array(),
);
?>
根据上传的信息,我们能知道访问的路径,如果是apache服务器__html
还会解析成html
,._php
也会即系成.php
,就能直接访问了,注意nginx则不会这样解析。
知识点补充
这边在针对漏洞的审计过程中补充需要关注的代码内容。
缓存机制
-
数据缓存(使用 cache_get()/cache_set()): 如论坛列表、置顶贴、在线列表、运行时数据等。
-
模板/包含编译缓存(写入 tmp/): 通过 _include() 在首次包含时把源文件与插件钩子合并后写到临时文件,下次直接读临时文件,属于"编译/合并缓存",非页面输出缓存。所以在修改htm的时候,需要把tmp/目录下生成的htm删除掉,才能有效。
发贴
-
入口链路: index.php -> index.inc.php 路由分发 -> route/forum.php -> 模板 view/htm/forum.htm
-
对应关系: 访问 /?forum-1.htm 会将 forum 作为路由名、1 作为 fid 传入论坛页处理器
代码位置(引用):
index.inc.php
php
$route = param(0, 'index');
// ...
switch ($route) {
// ...
case 'forum': include _include(APP_PATH.'route/forum.php'); break;
// ...
}
forum.php
scss
$fid = param(1, 0);
// ...
$forum = forum_read($fid);
empty($forum) AND message(3, lang('forum_not_exists'));
java
include _include(APP_PATH.'view/htm/forum.htm');
URL 的 forum-1.htm 被框架解析进 $_REQUEST,从而 param(0) 是 forum,param(1) 是 1。
perl
$_SERVER['REQUEST_URI'] = str_replace('/index.php?', '/', $_SERVER['REQUEST_URI']); // 兼容 iis6
$_REQUEST = array_merge($_COOKIE, $_POST, $_GET, xn_url_parse($_SERVER['REQUEST_URI']));
/?forum-1.htm 使用的文件是 route/forum.php(业务处理),并最终渲染 view/htm/forum.htm(模板)。
总结
本次审计揭示了 Xiuno BBS 4.0.4 在访问控制、输入验证和文件处理等方面存在多处安全隐患。CVE-2020-21493 的用户名枚举漏洞源于未充分验证用户输入,导致信息泄露;CVE-2020-21494 的安装向导遗留问题可能引发系统重置风险;CVE-2018-15559 的存储型 XSS 漏洞与管理员权限下的 HTML 解析机制相关;CVE-2020-19914 的文件上传漏洞则暴露出后缀处理和服务器解析配置的缺陷。这些问题反映出系统在安全设计上的不足,特别是在输入过滤、权限管理和文件安全检查方面。
此外,审计发现 Xiuno BBS 的缓存机制和路由设计高效但复杂,模板编译缓存(tmp/ 目录)可能导致开发调试不便,需手动清理。代码结构清晰,MVC 模式和钩子机制便于扩展,但在安全验证逻辑上存在疏漏,需加强。
修复建议
- 输入验证与过滤:增强用户输入检查,修复用户名枚举和 XSS 漏洞,建议对所有用户输入执行严格的 htmlspecialchars 或白名单过滤。
- 安装向导安全:安装完成后自动删除 install/ 目录,或增加锁定机制防止未授权访问。
- 文件上传安全:限制文件上传类型,规范化后缀处理,禁止危险扩展名(如 .php、.html)在 Apache 下的解析。
- 权限控制:细化管理员与普通用户在内容发布上的权限区分,防止 HTML 注入导致的 XSS。
- 代码维护:建议社区接管维护,定期更新依赖库,修复已知漏洞并适配新版 PHP 和 MySQL。
通过实施上述改进,Xiuno BBS 可显著提升安全性与可靠性,继续作为轻量级论坛解决方案服务于开发者与用户。