
挑战概述挑战名称: Authentification 1分类: CTF 存档 (密码学)来源: Breizh CTF解题数: 82难度: 中等 我用实习生实现的 AES-GCM 保护了我的网页应用好主意不是吗这个挑战涉及破解一个自定义的 AES-GCM 认证实现。核心漏洞在于 **nonce 重用**这会完全破坏 AES-GCM 的机密性和认证性。---## 背景知识AES-GCM Nonce 重用漏洞AES-GCM伽罗瓦/计数器模式是一种认证加密方案要求对同一密钥的每次加密操作使用唯一的 nonce。当 nonce 被重用时1. **生成相同的密钥流**C1 P1 ⊕ 密钥流C2 P2 ⊕ 密钥流2. **XOR 两个密文会揭示明文的 XOR**C1 ⊕ C2 P1 ⊕ P23. **如果已知一个明文**可以恢复另一个明文4. **认证标签可以被伪造**通过多项式运算可以恢复 GHASH 认证密钥H AES-GCM 通过加密计数器值生成密钥流。如果相同的 nonce 被重用就会生成相同的密钥流。对两个使用相同密钥流的密文进行 XOR 操作会揭示明文的 XOR。---## 漏洞分析实习生的实现很可能存在以下常见问题之一1. **固定的 nonce**例如 nonce b\x00 * 122. **Nonce 随机性不足**导致碰撞3. **计数器每次会话从 0 开始**当两个消息使用相同的 nonce 时可以恢复认证密钥H从而伪造任意消息的认证标签。---## 逐步利用过程### 1. 连接到服务bashnc archive.cryptohack.org 61277或使用 Pythonpythonfrom pwn import *conn remote(archive.cryptohack.org, 61277)2. 收集加密样本服务很可能提供加密令牌或认证数据。收集多个使用相同 nonce 的样本。python收集样本示例samples []for i in range(3):data conn.recvline()samples.append(json.loads(data))3. 识别 Nonce 重用从每个样本中提取 nonce。如果它们相同则该实现存在漏洞。pythonnonces [s[nonce] for s in samples]if len(set(nonces)) 1:print(存在漏洞检测到 Nonce 重用)4. 恢复 GHASH 密钥 (H)给定两个使用相同 nonce 且已知明文的密文可以恢复 GHASH 密钥。标签的形式为T ((H * (C ⊕ A)) ⊕ E_k(nonce||1)) * H ⊕ ...对于单块密文标签简化为T(C) C × H² ⊕ t差分方法T(C1) ⊕ T(C2) (C1 ⊕ C2) × H²通过发送不同密文的多个查询并观察标签差异我们可以恢复 H²然后得到 H。### 5. 伪造认证标签一旦恢复 H就可以伪造任意标签pythondef forge_tag(nonce, ciphertext, aad, H, E_k_nonce):# GCM 标签计算# ...### 6. 绕过认证使用伪造的标签以管理员身份认证或获取 flag。---## 攻击代码示例pythonfrom Crypto.Cipher import AESfrom Crypto.Util.number import long_to_bytes, bytes_to_longfrom Crypto.Util.strxor import strxorfrom sage.all import * # 用于有限域运算# GF(2^128) 与 GCM 多项式X GF(2).polynomial_ring().gen()poly X**128 X**7 X**2 X**1 1F GF(2**128, namea, moduluspoly)def gcm_mult(a, b):# GF(2^128) 中的乘法return fromF(toF(a) * toF(b))# 收集相同 nonce 的样本samples [...] # 从服务器获取# XOR 相同 nonce 的密文c1 bytes.fromhex(samples[0][ciphertext])c2 bytes.fromhex(samples[1][ciphertext])xor_result strxor(c1, c2)如果已知一个明文例如 adminfalse恢复另一个known_plaintext badminfalseunknown_plaintext strxor(xor_result, known_plaintext)从标签恢复 GHASH 密钥 H.. (在 GF(2^128) 中解线性方程组)伪造有效标签def forge_auth_tag(nonce, ciphertext, H, E_k_nonce):# 使用恢复的 H 实现 GCM 标签生成pass发送伪造的认证数据response json.dumps({ciphertext: forged_ciphertext,tag: forged_tag,nonce: nonce})conn.sendline(response)---另一种漏洞截断标签挑战还可能利用 **截断的认证标签**。正如在 Node.js 的 crypto 模块中看到的如果 authTagLength 没有正确验证标签可以被截断到只有 4 个字节。对于 2 字节的标签16 位只需要 65,536 次查询就可以暴力破解有效标签。python# 暴力破解有效的 2 字节标签for tag in range(65536):# 尝试使用截断标签解密response decrypt_with_tag(ciphertext, tag.to_bytes(2, big))if response ! Invalid tag:print(f找到有效标签: {tag:04x})break---## 防御与修复修复此漏洞的方法1. **永远不要对同一密钥重用 nonce**2. **使用确定性的 nonce 构造**例如计数器 随机前缀3. **考虑使用 AES-GCM-SIV**它具有 nonce 误用抵抗性4. **正确验证认证标签长度**5. **使用常数时间标签比较**以防止时序攻击Flag成功利用漏洞后服务器返回BZHCTF{...}---## 参考资料1. CryptoHack CTF 存档 - Authentification 12. GCM Nonce 重用攻击3. Boston Key Party CTF 2016 - GCM Writeup4. Node.js crypto 模块标签截断漏洞-关键要点这个挑战强调了几个重要的密码学原则1. Nonce 必须唯一AES-GCM 的安全性完全依赖于 nonce 的唯一性2. 认证与加密同等重要仅加密不足以保证安全3. 永远不要自己实现密码学使用经过验证的库和标准实现4. 了解常见漏洞模式Nonce 重用是加密中最常见的错误之一通过理解这些概念你不仅能够解决这个 CTF 挑战还能在实际应用中避免类似的安全漏洞。