Xiuno BBS 审计之问题14:依赖XXTEA 弱加密算法的鉴权令牌可被伪造

管理

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

问题:XXTEA 弱加密算法用于 Cookie/Token 加密,密钥派生仅 md5

现象

Xiuno BBS 4.0.4 的核心加密函数 xn_encrypt/xn_decrypt 在未加载 xiuno.so 扩展时,回退到纯 PHP 实现的 XXTEA 算法。XXTEA 是 1998 年设计的分组加密算法,并非密码学标准推荐算法(对比 AES),存在以下问题:

  • 算法本身非现代标准:XXTEA 未经 NIST/ISO 密码学评审,无 AEAD(无完整性/认证标签),密文可被篡改后仍解密为有效结构(无 MAC 校验)。

  • 密钥派生弱xn_key() 直接返回 $conf['auth_key'] 字符串,无 KDF(PBKDF2/HKDF/Argon2);xxtea_encrypt 内部将 key 字符串 str2long 转 4 个 32 位整数,不足补 0,密钥有效熵可能远低于预期。

  • 密文无完整性校验xn_decrypt 解密后直接返回,无 HMAC/签名验证,攻击者可构造/篡改密文(如 bbs_admin_tokenbbs_token)进行比特翻转/选择密文攻击。

  • 影响面广:该函数被用于加密 bbs_token(用户登录态)、bbs_admin_token(后台登录态)、xn_safe_key 等,一旦算法被攻破或密钥泄露,所有依赖它的鉴权令牌可被伪造。

源码证据

证据 1:xn_encrypt/xn_decrypt 回退到 XXTEA,无完整性校验 文件:xiunobbs_4.0.4/xiunophp/xn_encrypt.func.php 行 37-48

function xn_encrypt($txt, $key = '') {
	empty($key) AND $key = xn_key();
	$encrypt = function_exists('xiuno_encrypt') ? xiuno_encrypt($txt, $key) : xxtea_encrypt($txt, $key);
	return xn_urlencode(base64_encode($encrypt));
}

function xn_decrypt($txt, $key = '') {
	empty($key) AND $key = xn_key();
	$encrypt = base64_decode(xn_urldecode($txt));
	$ret = function_exists('xiuno_decrypt') ? xiuno_decrypt($encrypt, $key) : xxtea_decrypt($encrypt, $key);
	return $ret;
}

第 39 行:未加载 xiuno.so 时回退到 xxtea_encrypt;第 46 行解密后直接 return $ret,无 HMAC/签名校验。xn_encrypt 输出 base64_encode(xxtea_encrypt(plain, key)),无 IV、无认证标签。

证据 2:XXTEA 纯 PHP 实现,key 派生仅 str2long 补零 文件:xiunobbs_4.0.4/xiunophp/xn_encrypt.func.php 行 97-126

function xxtea_encrypt($str, $key) {
	if($str == '') return '';
	$v = xxtea_str2long($str, TRUE);
	$k = xxtea_str2long($key, FALSE);
	if (count($k) < 4) {
		for ($i = count($k); $i < 4; i++) {
			$k[$i] = 0;
		}
	}
	$n = count($v) - 1;

	$z = $v[$n];
	$y = $v[0];
	$delta = 0x9E3779B9;
	$q = floor(6 + 52 / ($n + 1));
	$sum = 0;
	while (0 < $q--) {
		$sum = xxtea_int32($sum + $delta);
		$e = $sum >> 2 & 3;
		for ($p = 0; $p < $n; $p++) {
			$y = $v[$p + 1];
			$mx = xxtea_int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ xxtea_int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
			$z = $v[$p] = xxtea_int32($v[$p] + $mx);
		}
		// ...
	}
	return xxtea_long2str($v, FALSE);
}

第 100-105 行:$k = xxtea_str2long($key, FALSE),key 不足 4 个 32 位整数时补 0($k[$i] = 0),短密钥的有效熵被零填充稀释;无 KDF,密钥直接作为算法输入。

证据 3:xn_key 直接返回 auth_key 字符串,无 KDF 文件:xiunobbs_4.0.4/xiunophp/xn_encrypt.func.php 行 16-19

function xn_key($fromso = TRUE) {
	$conf = _SERVER('conf');
	return ($fromso && function_exists('xiuno_key')) ? xiuno_key() : (isset($conf['auth_key']) ? $conf['auth_key'] : '');
}

第 18 行:未加载扩展时直接返回 $conf['auth_key'] 字符串作为加密密钥,无 PBKDF2/HKDF 拉伸。该 auth_key 在默认配置中为硬编码值(见独立审计文件),密钥强度进一步降低。

证据 4:XXTEA 加密用于鉴权令牌 文件:xiunobbs_4.0.4/model/user.func.php 行 348-358

function user_token_gen($uid) {
	global $ip, $time, $conf;
	
	// hook model_user_token_gen_start.php
	
	$tokenkey = md5(xn_key());
	$token = xn_encrypt("$ip	$time	$uid", $tokenkey);
	
	// hook model_user_token_gen_end.php
	
	return $token;
}

第 353-354 行:bbs_token 内容 $ip\t$time\t$uidxn_encrypt(XXTEA)加密。bbs_admin_tokenadmin.func.php 行 58)同样用 xn_encrypt。若 XXTEA 密文可被篡改/伪造,攻击者可构造任意 uid 的有效令牌,实现身份伪造。

风险等级与结论

风险等级:中高危

结论:

  1. 核心加密采用 XXTEA(非现代标准、无 AEAD、无完整性校验),纯 PHP 回退实现,密钥派生仅 str2long 补零,无 KDF。

  2. xn_decrypt 解密后无 HMAC/签名校验,密文可被篡改;结合明文结构已知($ip\t$time\t$uid),存在选择密文/比特翻转攻击空间。

  3. 该加密保护 bbs_token/bbs_admin_token 等鉴权令牌,算法弱点直接危及身份认证体系。

  4. auth_key 默认硬编码(见独立审计文件),密钥强度问题叠加,进一步降低伪造令牌难度。

  5. 修复建议:改用 openssl_encrypt/sodium_crypto_secretbox(AES-256-GCM 或 XSalsa20-Poly1305)等现代 AEAD 算法;密钥派生使用 HKDF/PBKDF2;密文包含随机 IV 与认证标签;解密后校验 MAC;auth_key 强制随机生成且不少于 32 字节。

最新回复

请先登录后再回复 登录

uid:1 管理
关注
随遇而安,随缘而行
发帖 81
评论 348
粉丝 11
关注 1
发新帖
目录
Xiuno BBS 审计之问题14:依赖XXTEA 弱加密算法的鉴权令牌可被伪造