Xiuno BBS 审计之问题01:后台所有操作无 CSRF Token 校验
贰先生 8小时前

问题:后台所有操作无 CSRF Token 校验

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

现象

Xiuno BBS 4.0.4 后台鉴权仅依赖 bbs_admin_token Cookie,admin_token_check() 只校验该 Cookie 是否能被 xn_decrypt 解密且未过期,全程不校验任何 CSRF Token(既不校验请求体中的 token 字段,也不校验 Origin/Referer 头)。这意味着攻击者只需诱导已登录管理员访问恶意页面,即可通过跨站请求伪造触发后台任意写操作:增删管理员、修改站点配置、上传/安装插件、清空数据库等。

后台 admin/route/*.php 中所有 POST 分支均未调用任何 token 校验函数,admin_token_check() 是唯一的鉴权入口,且其内部不含任何 anti-CSRF 机制。

源码证据

证据 1:后台鉴权函数仅校验 Cookie,无 CSRF Token 文件:xiunobbs_4.0.4/admin/admin.func.php 行 8-45

function admin_token_check() {
	global $longip, $time, $useragent, $conf;
	$useragent_md5 = md5($useragent);
	
	//$key = md5($longip.$useragent_md5.$conf['auth_key']); // 有些环境是动态 IP
	$key = md5((XN_ADMIN_BIND_IP ? $longip : '').$useragent_md5.xn_key());
	
	// hook admin_token_check_start.php
	
	$admin_token = param('bbs_admin_token');
	if(empty($admin_token)) {
		$_REQUEST[0] = 'index';
		$_REQUEST[1] = 'login';
	} else {
		$s = xn_decrypt($admin_token, $key);
		if(empty($s)) {
			setcookie('bbs_admin_token', '', 0, '', '', '', TRUE);
			message(-1, lang('admin_token_expiry'));
		}
		list($_ip, $_time) = explode("\t", $s);
		// 后台超过 3600 自动退出。
		if((XN_ADMIN_BIND_IP && $_ip != $longip || !XN_ADMIN_BIND_IP) && $time - $_time > 3600) {
			setcookie('bbs_admin_token', '', 0, '', '', '', TRUE);
			message(-1, lang('admin_token_expiry'));
		}
		// 超过半小时,重新发新令牌,防止过期
		if($time - $_time > 1800) {
			admin_token_set();
		}
	}
}

第 17 行:$admin_token = param('bbs_admin_token'); 仅从 Cookie 取 token,无任何 POST/GET token 字段校验,无 Referer/Origin 校验。默认 XN_ADMIN_BIND_IP 为空(行 6),IP 绑定不生效,CSRF 不受 IP 限制。

证据 2:后台 POST 操作均无 token 校验(示例) 文件:xiunobbs_4.0.4/admin/route/index.php 行 21-40

} else if($method == 'POST') {
	// hook admin_index_login_post_start.php
	$password = param('password');
	if(md5($password.$user['salt']) != $user['password']) {
		xn_log('password error. uid:'.$user['uid'].' - ******'.substr($password, -6), 'admin_login_error');
		message('password', lang('password_incorrect'));
	}
	admin_token_set();
	xn_log('login successed. uid:'.$user['uid'], 'admin_login');
	message(0, jump(lang('login_successfully'), '.'));
}

登录 POST 不校验 token。其余后台路由(admin/route/setting.phpadmin/route/user.phpadmin/route/forum.phpadmin/route/plugin.php 等)的 POST 分支同样仅依赖 admin_token_check(),无独立 token 校验。

证据 3:插件安装/卸载等高危操作无 token 文件:xiunobbs_4.0.4/admin/route/plugin.php 行 155-201

} elseif($action == 'install') {
	plugin_lock_start();
	$dir = param_word(2);
	plugin_check_exists($dir);
	$name = $plugins[$dir]['name'];
	plugin_check_dependency($dir, 'install');
	plugin_install($dir);
	$installfile = APP_PATH."plugin/$dir/install.php";
	if(is_file($installfile)) {
		include _include($installfile);
	}
	plugin_lock_end();
	// ...
	$msg = lang('plugin_install_sucessfully', array('name'=>$name));
	message(0, jump($msg, http_referer(), 3));
}

插件安装会 include 插件目录下的 install.php(第 173-175 行),属极高危操作,但全程无 CSRF Token。攻击者构造 <img src="http://victim/admin/plugin-install-恶意插件"> 即可诱导管理员访问时自动安装含恶意 install.php 的插件,实现 RCE。

风险等级与结论

风险等级:高危

结论:

  1. 后台所有 POST 操作无 CSRF Token,鉴权仅靠 Cookie,构成完整的 CSRF 漏洞。
  2. 结合 bbs_admin_token Cookie 未设 SameSite 属性(见 Cookie 安全审计),浏览器默认不会拦截跨站请求携带 Cookie,CSRF 可直接生效。
  3. 影响面覆盖后台全部功能:增删管理员、改配置、安装/卸载插件(含 include install.php → RCE)、删帖删版块。
  4. 修复建议:在 admin_token_check() 中对非 GET 请求强制校验请求体内的 CSRF Token(-session 绑定、一次性 token);校验 Origin/Referer 头;Cookie 设置 SameSite=Lax/Strict;敏感操作(插件安装、配置修改)追加二次密码确认。
最新回复 (2)
全部楼主
  • Airhelym
    8小时前 2
    0
    代码块好像没有显示出来?
  • 贰先生 楼主
    8小时前 3
    1
    Airhelym 代码块好像没有显示出来?
    ok了 ,这个站的编辑器有点难驾驭
返回