返回论坛

哈希函数的隐秘陷阱:长度扩展攻击如何突破服务端权限验证

查找币 漏洞披露 安全研究 Web3安全 区块链安全

查找币安全研究院

钱包恢复评估 | 链上取证分析 | Web3 事件响应
以合法授权、证据保全、隐私保护和可复核流程为前提,不要求用户在线提交完整私钥或助记词。

查看研究院 研究报告中心
## 概述 在Web3安全领域,哈希函数的安全性往往被开发者视为理所当然。然而,某些广泛使用的哈希算法(如MD5、SHA-1、SHA-256)存在一个鲜为人知的特性——**长度扩展攻击**。这种攻击利用Merkle-Damgård结构的内部机制,允许攻击者在不知道原始消息的情况下,基于已知的哈希值构造出新的有效哈希。 本文将深入剖析这一攻击原理,并通过真实场景演示其如何导致服务端权限验证被绕过,最终给出针对性的防护方案。 ## 攻击原理:Merkle-Damgård结构的弱点 ### 哈希函数的内部工作方式 SHA-256等哈希函数采用Merkle-Damgård结构,其处理流程如下: 1. **分块处理**:将输入消息分割为固定长度的块(SHA-256为512比特) 2. **迭代压缩**:每个块的哈希值依赖于前一个块的输出状态 3. **填充规则**:对不足块长的数据进行标准化填充 ### 长度扩展攻击的核心机制 攻击的关键在于:**一旦计算出`H(message)`,我们就获得了哈希函数的内部状态。从这个状态出发,可以继续添加更多数据块,无需知道原始消息内容。** 具体来说,攻击者只需知道: - 原始哈希值 `H(message)` - 原始消息的长度(或可推断) 即可计算出:`H(message || padding || extension)`,其中: - `padding` 是根据哈希规范添加的填充数据 - `extension` 是攻击者想要附加的新数据 ## 漏洞场景:不安全的服务端验证模式 ### 典型验证流程 假设某Web3服务端采用以下验证模式: 1. **登录阶段**:服务端使用 `SecretKey + user_id + user_name` 生成哈希,下发给客户端 2. **权限操作阶段**:客户端提交 `user_id + user_name + role` 及哈希值,服务端验证通过后执行权限变更 ### 伪代码示例 ```python # 登录接口 def login_handler(user_id, user_name): data = f"user_id={user_id}&user_name={user_name}" secret = "Length_extension_attack_secret" # 30位密钥 hash_value = sha256(secret + data) return {"data": data, "hash": hash_value} # 权限修改接口 def modify_role_handler(data, hash_value): # 解析参数 params = parse_query_string(data) user_id = params["user_id"] user_name = params["user_name"] role = params.get("role", "user") # 重新计算哈希 new_data = f"user_id={user_id}&user_name={user_name}&role={role}" expected_hash = sha256(secret + new_data) if hash_value == expected_hash: # 执行权限变更 update_role(user_id, role) ``` ## 攻击流程:从哈希值到越权 ### 第一步:获取初始哈希 通过登录接口,攻击者获取到: - `data = "user_id=1&user_name=aa"` - `hash = "37d310d3465506486431fb2c2eb163f0f470479703f66dc9e5fdead8a3390c68"` ### 第二步:推断消息长度 由于密钥长度为30字节,攻击者只需进行30次迭代测试,即可确定原始消息的准确长度。 ### 第三步:构造恶意负载 攻击者希望添加 `&role=admin` 参数。通过长度扩展攻击: ```python # 使用长度扩展攻击库 from sha256_extender import extend original_hash = "37d310d3465506486431fb2c2eb163f0f470479703f66dc9e5fdead8a3390c68" original_data = "user_id=1&user_name=aa" extension = "&role=admin" secret_length = 30 # 密钥长度 new_hash, new_data = extend( hash=original_hash, data=original_data, extension=extension, secret_length=secret_length ) ``` ### 第四步:提交恶意请求 攻击者将 `new_data` 和 `new_hash` 提交至权限修改接口。服务端解析 `new_data` 时,由于包含 `&role=admin`,将赋予攻击者管理员权限。 ## 受影响算法对比 | 算法 | 抗碰撞性 | 抗预映像性 | 受长度扩展攻击影响 | |------|---------|-----------|-----------------| | MD5 | 2^18 | 2^123.4 | ✅ 易受攻击 | | SHA-1 | 2^61.2 | 2^160 | ✅ 易受攻击 | | SHA-256 | 2^65.5 | 2^254.9 | ✅ 易受攻击 | | SHA-512 | 2^32.5 | 2^511.5 | ✅ 易受攻击 | | SHA-3 | 2^50 | 未知 | ❌ 不易受攻击 | | BLAKE2s | 2^112 | 2^241 | ❌ 不易受攻击 | | BLAKE2b | 2^224 | 2^481 | ❌ 不易受攻击 | ## 防护建议 ### 方案一:使用抗长度扩展的哈希函数 - **SHA-3**:采用海绵结构,天然抵抗长度扩展攻击 - **BLAKE2**:基于ChaCha流密码设计,同样不受影响 ### 方案二:采用HMAC结构 HMAC(哈希消息认证码)通过双重哈希机制有效防御长度扩展攻击: ```python # 安全的验证方式 def secure_verify(data, secret): # HMAC-SHA256 hmac_hash = hmac.new(secret, data, hashlib.sha256).hexdigest() return hmac_hash # 或者使用密钥衍生 def alternative_verify(data, secret): # 先对密钥进行哈希 hashed_secret = sha256(secret) return sha256(hashed_secret + data) ``` ### 方案三:规范数据格式 - 在数据前后添加固定分隔符或元数据 - 使用JSON等结构化格式替代简单的字符串拼接 - 对参数顺序和格式进行严格校验 ## 结语 长度扩展攻击是Web3安全领域一个常被忽视的隐患。它提醒我们:**哈希函数的“安全”并非绝对,算法的选择直接影响系统的安全性**。对于涉及权限验证、交易签名的场景,建议优先采用SHA-3、BLAKE2等新一代哈希算法,或通过HMAC结构增强现有方案的安全性。 本文由查找币安全团队整理发布 --- **参考资源:** - [RFC 6234 - SHA哈希函数规范](https://www.rfc-editor.org/rfc/rfc6234) - [SHA-256长度扩展攻击实现示例](https://github.com/skerkour/kerkour.com/tree/main/blog/2023/sha256_length_extension_attacks)
在论坛中查看和回复