CBC Padding Oracle Attack (Vaudenay)
- •
What it is
- •
Vaudenay's classic attack: if a service decrypts attacker-supplied CBC ciphertext and reveals — even just through a Boolean "valid/invalid" signal — whether the resulting plaintext has correct PKCS#7 padding, an attacker can recover the entire plaintext without ever knowing the key. Working one byte at a time from the last byte of a block backward, the attacker tweaks a single byte of the previous ciphertext block (or the IV, for the first block) and brute-forces all 256 values until the oracle reports valid padding — from which the true plaintext byte at that position follows directly.
- •
- •
When to apply
- •
A CBC decryption endpoint reveals (directly, via an error message, or via any behavioral difference) whether decrypted padding was valid, and lets you submit arbitrary ciphertext/IV pairs.
- •
- •
Math
- •
For the last byte of a block, a forged previous-block byte makes padding valid when . Since , once is found, . Each earlier byte repeats this against a higher target padding value (0x02, 0x03, ...), holding the already-recovered suffix fixed to that new padding value.
- •
- •
Worked example
- •
For the final byte, a valid response suggests . To distinguish genuine
0x01padding from an unchanged longer valid padding, perturb byte 14 and query again. Continue only if validity survives, then force the recovered suffix to0x02,0x03, and so on.
- •
- •
Python
- •
def recover_block(oracle, prev_block, target_block): recovered = bytearray(16) crafted = bytearray(prev_block) for idx in range(15, -1, -1): pad = 16 - idx for j in range(15, idx, -1): crafted[j] = prev_block[j] ^ recovered[j] ^ pad for guess in range(256): crafted[idx] = prev_block[idx] ^ guess ^ pad if oracle(bytes(crafted) + target_block): recovered[idx] = guess break return bytes(recovered)
- •
- •
- •
Cards
- •
What single piece of information does the classic padding oracle attack need from the server?
- •
A Boolean signal (however indirect) telling you whether the decrypted plaintext had valid PKCS#7 padding.
- •
- •
How do you recover a plaintext byte once you've found a "crafted" previous-block byte that makes padding valid?
- •
XOR that crafted byte with the corresponding real previous-ciphertext byte and the target padding value.
- •
- •