🌭 代码审计-xiuno BBS

引言

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

    vbnet 复制代码
    FROM php:fpm=>FROM php:7.3-fpm
    
    php:php:7.3-fpm
  • 修改nginx的镜像文件nginx/Dockerfile

    ini 复制代码
    FROM nginx:latest=>>FROM nginx:1.29-perl
  • 修改mysql的镜像文件mysql/Dockerfile

    ini 复制代码
    FROM mysql:5.7=>FROM mysql:5.7.24
  • 修改网络配置

    ini 复制代码
    DOCKER_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

初始化系统

  1. 浏览器打开地址,默认端口是8018,选择语言,默认即可,点击下一步

  2. 点击同意协议

  3. 环境检查,点击下一步

  4. 选择InnoDB,数据库的服务器、用户名和密码分别填写.env里面对应的MYSQL_SERVER_ADDRESSMYSQL_USERMYSQL_PASSWORD,点击下一步

  5. 安装成功,并点击确认

  6. 到此可以正常使用了。

漏洞复现

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 模式和钩子机制便于扩展,但在安全验证逻辑上存在疏漏,需加强。

修复建议
  1. 输入验证与过滤:增强用户输入检查,修复用户名枚举和 XSS 漏洞,建议对所有用户输入执行严格的 htmlspecialchars 或白名单过滤。
  2. 安装向导安全:安装完成后自动删除 install/ 目录,或增加锁定机制防止未授权访问。
  3. 文件上传安全:限制文件上传类型,规范化后缀处理,禁止危险扩展名(如 .php、.html)在 Apache 下的解析。
  4. 权限控制:细化管理员与普通用户在内容发布上的权限区分,防止 HTML 注入导致的 XSS。
  5. 代码维护:建议社区接管维护,定期更新依赖库,修复已知漏洞并适配新版 PHP 和 MySQL。

通过实施上述改进,Xiuno BBS 可显著提升安全性与可靠性,继续作为轻量级论坛解决方案服务于开发者与用户。

相关推荐
你的人类朋友3 小时前
🍃说说Base64
前端·后端·安全
BingoGo3 小时前
PHP 8.2 vs PHP 8.3 对比:新功能、性能提升和迁移技巧
后端·php
余防3 小时前
CSRF跨站请求伪造
前端·安全·web安全·csrf
Yyyy4824 小时前
LVS三种模式及原理
服务器·php·lvs
七夜zippoe4 小时前
微服务配置中心高可用设计:从踩坑到落地的实战指南(二)
微服务·架构·php
愚公搬代码4 小时前
【愚公系列】《人工智能70年》044-数据科学崛起(安全与隐私,硬币的另一面)
人工智能·安全
苏琢玉5 小时前
作为 PHP 开发者,我第一次用 Go 写了个桌面应用
node.js·go·php
宁雨桥5 小时前
前端登录加密实战:从原理到落地,守护用户密码安全
前端·安全·状态模式
JaguarJack5 小时前
PHP 8.2 vs PHP 8.3 对比:新功能、性能提升和迁移技巧
后端·php