此文章为XIUNOX版本重构审计时发现问题,XIUNOX版本已优化修复此问题。分享出来方便后续想基于xiuno bbs4.0.4版本制作维护版本或插件模板等需求的开发者和站长参考。
现象
Xiuno BBS 4.0.4 通过 // hook xxx 和 <!--{hook xxx}--> 标记提供插件扩展点。经统计全站共约 697 处钩子点分布在 63 个文件中,看似覆盖面广,但关键业务流程(登录前置校验、发帖审核、支付/订单、附件上传、数据删除)的钩子点严重不足,且部分关键节点(如登录成功后写 session 前、密码校验失败、附件入库前、用户被删除前)完全缺失钩子,导致插件无法实现登录二次验证、发帖内容审核、支付集成、附件病 毒扫描等常见需求。
源码证据
1. 钩子点总量统计(Grep count)
// hook → 697 处 / 63 个文件
<!--{hook → 0 处(模板钩子用 // hook 同一正则匹配,源码注释 <!--{hook 在编译期被替换为 // hook,见 plugin.func.php 第 297 行)
2. 关键流程:登录缺关键钩子(user_login_post_end 在 message 之前但无登录失败钩子)
文件:xiunobbs_4.0.4/route/user.php 第 68-104 行
} else if($method == 'POST') {
$email = param('email');
$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'));
}
!is_password($password, $err) AND message('password', $err);
md5($password.$_user['salt']) != $_user['password'] AND message('password', lang('password_incorrect'));
user_update($_user['uid'], array('login_ip'=>$longip, 'login_date' =>$time , 'logins+'=>1));
$uid = $_user['uid'];
$_SESSION['uid'] = $uid;
user_token_set($_user['uid']);
message(0, lang('user_login_successfully'));
}
缺失:无 user_login_pre_check(登录前可由插件接管二次验证/图形验证码/限制 IP)、无 user_login_failed(登录失败可记录风控/锁定账号)、无 user_login_success_before_session(写 session 前可改写登录态)。
3. 关键流程:发帖创建无审核前置钩子,插件无法拦截违规内容
文件:xiunobbs_4.0.4/route/post.php 第 44-71 行
} else {
$message = param('message', '', FALSE);
empty($message) AND message('message', lang('please_input_message'));
$doctype = param('doctype', 0);
xn_strlen($message) > 2028000 AND message('message', lang('message_too_long'));
$thread['top'] > 0 AND thread_top_cache_delete();
$quotepid = param('quotepid', 0);
$quotepost = post__read($quotepid);
(!$quotepost || $quotepost['tid'] != $tid) AND $quotepid = 0;
$post = array(
'tid'=>$tid,
'uid'=>$uid,
'create_date'=>$time,
'userip'=>$longip,
'isfirst'=>0,
'doctype'=>$doctype,
'quotepid'=>$quotepid,
'message'=>$message,
);
$pid = post_create($post, $fid, $gid);
empty($pid) AND message(-1, lang('create_post_failed'));
post_post_start 之后直接 post_create 入库,无 post_create_before 钩子供插件做内容审核/敏感词过滤/机器审核。
4. 关键流程:用户删除无前置钩子,无法级联清理第三方数据
文件:xiunobbs_4.0.4/route/post.php 第 181-220 行(仅 delete 后置钩子)
} elseif($action == 'delete') {
$pid = param(2, 0);
if($method != 'POST') message(-1, lang('method_error'));
$post = post_read($pid);
if($isfirst) {
thread_delete($tid);
} else {
post_delete($pid);
}
message(0, lang('delete_successfully'));
}
5. 完全缺失的钩子点(无支付/订单流程)
Grep 全站无 pay、order、payment 关键字钩子,无任何支付相关扩展点,无法通过插件接入支付宝/微信支付。
风险等级与结论
架构缺陷(严重)
危害:
- 关键安全流程(登录、发帖、删除)无前置钩子,插件无法接管风控/审核/级联清理
- 无支付/订单钩子,无法扩展为付费社区、积分商城等业务
- 钩子分布不均(统计显示 697 个钩子集中在 model/*.func.php 内部,关键路由流程钩子稀疏)
- 钩子命名不统一(
xxx_start、xxx_end、xxx_before、xxx_after、xxx_middle 混用),插件作者难以预测
修复建议:
- 为所有写操作(create/update/delete)统一增加
_before 与 _after 钩子对
- 登录流程增加
user_login_pre_check、user_login_failed、user_login_success_before_session
- 引入支付/订单抽象层与对应钩子点
- 制定钩子命名规范文档,并在
auto_add_hook.php 工具中校验