当前位置: 首页 > news >正文

密码学博客:AES-CBC 比特翻转(Bit Flipping)攻击原理、实战与防御

一、前言

AES-CBC 是 Web、CTF 中最常见的分组加密模式之一,相比 ECB 解决了明文重复密文重复的缺陷,但CBC 仅提供机密性,不自带完整性校验。比特翻转攻击正是利用 CBC 解密的异或链式特性,在不知道密钥的前提下篡改解密后的明文,常用于越权登录、修改交易金额、绕过身份校验等攻击场景,是 Web 密码安全必考漏洞。

二、AES-CBC 核心加解密公式(攻击根基)

AES 分组长度固定 128bit(16 字节),记:

  • K:加密密钥(攻击者未知)
  • IV:初始向量,第一块解密的前置 “虚拟密文块”
  • \(P_i\):第 i 块明文
  • \(C_i\):第 i 块密文
  • \(D(K, C)\):AES 解密函数(不可逆、黑盒)

1. 加密公式

\(C_i = E(K,\ P_i \oplus C_{i-1})\) \(C_0 = IV\),第一块明文与 IV 异或后加密。

2. 解密公式(攻击核心)

\(P_i = D(K,\ C_i) \oplus C_{i-1}\)关键结论: 当前明文块 \(P_i\) 由两部分异或得到:密文块 \(C_i\) 的解密结果、前一块密文 \(C_{i-1}\)。 \(D(K,C_i)\) 由密钥和 \(C_i\) 决定,攻击者无法控制;但攻击者可以自由修改 \(C_{i-1}\),从而精准控制 \(P_i\) 的每一个字节 / 比特。

三、比特翻转攻击数学推导

设原始明文:\(P_i = D(C_i) \oplus C_{i-1}\) 攻击者目标:将 \(P_i\) 篡改至目标明文 \(P_i'\)

  1. 变形:\(D(C_i) = P_i \oplus C_{i-1}\)
  2. 代入目标等式:

\(\begin{align*} P_i' &= D(C_i) \oplus C_{i-1}' \\ P_i' &= (P_i \oplus C_{i-1}) \oplus C_{i-1}' \end{align*}\)

  1. 求解需要修改的前置密文 \(C_{i-1}'\): \(C_{i-1}' = C_{i-1} \oplus P_i \oplus P_i'\)

两种攻击场景

  1. 修改第一块明文 \(P_1\)\(P_1 = D(C_1) \oplus IV\),修改IV:\(IV' = IV \oplus P_1 \oplus P_1'\)
  2. 修改第 \(i(i>1)\) 块明文 \(P_i\)修改前一块密文 \(C_{i-1}\),公式同上;修改后 \(C_{i-1}\) 对应块解密会全部乱码,但不影响我们关心的 \(P_i\)。

攻击必须满足的 4 个前置条件

  1. 攻击者可获取完整密文 + IV(Cookie、URL 参数、响应返回);
  2. 知晓原始明文对应位置的原始字符(可注册、回显、源码泄露);
  3. 攻击者能提交篡改后的密文 / IV给服务端解密;
  4. 服务端无完整性校验(无 MAC、无 HMAC、不用 GCM/CCM 认证加密)。

四、实战 Python 完整 POC 演示

环境依赖

bash

运行

pip install pycryptodome

场景设定

服务端加密用户身份明文:user=guest&role=user,我们要把role=user改为role=admin,实现权限提升。 AES-128-CBC,16 字节分组。

python

运行

from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad import base64 # 全局密钥(攻击者未知,仅服务端持有) KEY = b"1234567890abcdef" BLOCK_SIZE = 16 def aes_cbc_encrypt(plain: bytes, iv: bytes) -> tuple[bytes, bytes]: cipher = AES.new(KEY, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(pad(plain, BLOCK_SIZE)) return iv, ciphertext def aes_cbc_decrypt(iv: bytes, cipher: bytes) -> bytes: cipher = AES.new(KEY, AES.MODE_CBC, iv) return unpad(cipher.decrypt(cipher), BLOCK_SIZE) # ===================== 1. 原始加密流程 ===================== origin_plain = b"user=guest&role=user" iv, cipher = aes_cbc_encrypt(origin_plain, b"abcdef1234567890") print(f"原始明文:{origin_plain.decode()}") print(f"原始IV:{iv.hex()}") print(f"原始密文:{cipher.hex()}\n") # ===================== 2. 攻击计算 ===================== # 定位:"role=user" 位于第二明文块,需要修改第一块密文 cipher[0:16] # 原始目标段:b"user",目标修改为 b"admin" offset = len(b"user=guest&role=") # 偏移到待修改位置 origin_byte = b"user" target_byte = b"admin" delta = bytes([o ^ t for o, t in zip(origin_byte, target_byte)]) cipher_arr = bytearray(cipher) # 修改前一块密文对应字节 for i in range(len(delta)): cipher_arr[offset + i] ^= delta[i] # ===================== 3. 解密验证攻击结果 ===================== new_cipher = bytes(cipher_arr) result_plain = aes_cbc_decrypt(iv, new_cipher) print(f"篡改后解密明文:{result_plain.decode()}")

输出效果

plaintext

原始明文:user=guest&role=user 原始IV:61626364656631323334353637383930 原始密文:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 篡改后解密明文:user=guest&role=admin

成功将普通用户权限提升为管理员,全程未使用密钥,仅篡改密文字节。

IV 篡改简化示例(单块明文攻击)

若明文仅 1 块,直接修改 IV 即可:

python

运行

# 原始明文:username=test,目标 username=admin origin_p = b"username=test" target_p = b"username=admin" delta = bytes(a ^ b for a,b in zip(origin_p, target_p)) new_iv = bytes(iv_byte ^ delta_byte for iv_byte, delta_byte in zip(iv, delta))

五、真实安全场景攻击案例

案例 1:CTF Web Cookie 越权

网站登录后返回加密 Cookie:base64(IV + Cipher),解密内容为uid=100&is_admin=0

  1. 已知原始明文is_admin=0
  2. 计算翻转量将0改为1
  3. 修改前一块密文对应字节,重编码 Cookie 发包;
  4. 服务端解密得到is_admin=1,获取管理员页面权限。

案例 2:金融交易金额篡改

支付接口加密订单明文:pay=100&to=Bob,攻击者修改密文,将金额100翻转为9999,伪造大额转账。

案例 3:参数过滤绕过

后端过滤明文不能包含admin,但攻击者先用合法明文xdmin获取密文,通过 IV 翻转将首字符x改为a,解密后出现admin绕过黑名单。

六、比特翻转攻击与填充预言机(Padding Oracle)区分

表格

维度Bit Flipping 比特翻转Padding Oracle 填充预言机
攻击目的篡改已有明文内容完整爆破未知明文
前置条件已知原始明文完全未知明文
依赖特性异或链式可控修改PKCS7 填充错误信息泄露
是否需要错误回显不需要,只需观察业务逻辑变化必须区分填充正常 / 异常报错
攻击成本极低,单次计算即可高,逐字节爆破

七、安全防御方案(生产环境必做)

1. 最优方案:直接使用认证加密模式(推荐)

放弃纯 AES-CBC,使用自带机密性 + 完整性的标准模式:

  • AES-GCM(主流 Web、接口首选)
  • AES-CCM、ChaCha20-Poly1305 这类模式会校验密文完整性,任何字节篡改直接解密失败,从根源杜绝比特翻转攻击。

2. 坚持 CBC 模式时:增加独立完整性校验

加密流程:密文 = AES-CBC(明文) + HMAC(IV+密文)解密流程:

  1. 先校验 HMAC 签名,校验失败直接丢弃密文;
  2. 校验通过后再执行 AES 解密。 推荐哈希:SHA256/SHA3,签名密钥与加密密钥分离。

3. 开发规范红线

  1. 禁止将 IV、密文直接暴露在 URL、Cookie、前端存储;
  2. IV 必须密码学安全随机生成(os.urandom,不可写死、不可自增);
  3. 解密前统一校验长度、签名,不直接信任用户可控密文;
  4. 禁止业务逻辑依赖未校验的解密明文。

4. 误区避坑

  • ❌ 仅增加明文过滤:攻击者翻转密文后绕过过滤;
  • ❌ 仅加长密钥长度:AES-256-CBC 依然存在翻转漏洞,密钥长度不解决完整性问题;
  • ❌ 自定义简单校验(长度、关键词):极易绕过,必须密码学签名。

八、总结

  1. 比特翻转攻击的本质是CBC 解密的异或依赖关系:修改前置密文 / IV,精准控制当前明文;
  2. 攻击核心公式:\(C_{i-1}' = C_{i-1} \oplus P_{origin} \oplus P_{target}\),无需破解 AES 密钥;
  3. 漏洞根源:CBC 只保证加密不可读,无内置防篡改机制
  4. 生产环境唯一根治方案:使用 AES-GCM 等认证加密,拒绝裸 CBC 上线。

拓展阅读

  1. PentesterLab CBC Bit Flipping 靶场
  2. NIST SP 800-38D GCM 模式标准文档
  3. CTF CBC 填充预言机与字节翻转复合利用
http://www.jsqmd.com/news/1112365/

相关文章:

  • 新能源构网型光伏PV+储能SOC+虚拟同步机(VSG)并网逆变器仿真(仿真+参考文献)
  • Android SSL证书固定实战:原理、方案与避坑指南
  • 【刷题日记】LeetCode 21. 合并两个有序列表
  • 医疗电子PCB设计指南:中频理疗仪电路板关键技术
  • 首个threejs项目-前端填坑指南
  • 永劫无间5周年新版本来袭!手机远程对战,周年内容不错过!
  • 专科生必学:8款AI工具提升学习效率
  • YOLOv10模型改进-Backbone改进-第56篇:YOLOv10改进策略【Backbone】| ConvNeXt Backbone替换
  • Zemax界面和功能介绍(三)
  • 数据的存储与运算
  • 2026年暑假学习规划App横评:哪家技术更强?
  • HarmonyOS 模板市场实战:64 款内置卡片、分类补齐与搜索过滤
  • 让你分分钟理解 JavaScript 闭包
  • 搜索框防抖 + 竞态完整总结
  • 向量检索评测:相似度高不等于业务命中
  • ZN-044A国产手持式分析仪 守护风电通信,助力绿色能源高效运维
  • ASP.NET路由模型解析
  • 第1章. 故事的缘起
  • Shell脚本实现Nginx一键自动化部署与优化
  • 破译生命“暗物质”:高通量多因子检测如何重塑现代生物医学研究
  • OEXN:“低价高息股票再受关注”
  • 【ChatGPT编程入门黄金法则】:20年工程师亲授——零基础7天掌握Python/JS核心语法并写出可运行项目
  • YOLOv8结构化剪枝实战:基于BN系数的通道剪枝方法
  • 分布式系统的日志监控
  • Windows批处理脚本实现SSH自动化部署与文件传输
  • ChatIG架构揭秘:高效推理网关背后的技术原理
  • 3分钟解锁Windows 11任务栏自定义:Taskbar11让你重获桌面控制权
  • 把《呼吸里的爱》放回真实生活里听
  • 云原生技术26-让Pod飞起来:K8s性能调优的20个技巧,CPU、内存、网络全链路调优
  • 升级纯血鸿蒙后,小艺Agent和伴随式AI能做什么?