Cryptography / Failure Analysis
Symmetric Mode Attacks: ECB, CBC & CTR
Evaluating symmetric block cipher modes requires understanding their specific cryptanalytic failure modes. Unauthenticated cipher modes fail in distinct ways: Electronic Codebook (ECB) leaks structural patterns, Cipher Block Chaining (CBC) is vulnerable to bit-flipping and padding oracle attacks, and Counter (CTR) mode collapses into a two-time pad when nonces repeat under the same key.
Attack Summary Matrix
| Cipher Mode | Vulnerability / Failure Mode | Root Cause | Impact | Defensive Countermeasure |
|---|---|---|---|---|
| AES-CBC | Bit-Flipping Malleability & Padding Oracles | Ciphertext block N XORed into plaintext block N+1 during decryption | Attacker flips arbitrary bits in block N+1 without knowing the key | Use AEAD (AES-GCM) or apply Encrypt-then-MAC (HMAC-SHA256). |
| AES-CTR | Two-Time Pad Keystream Reuse | Same counter value reused under the same key generates duplicate keystream | C1 ⊕ C2 = P1 ⊕ P2 without knowing key; recovering either full plaintext from that XOR sum additionally requires the attacker to already know or correctly guess predictable content in the other message | Never Repeat a Counter-Block Input Under the Same Key: generic CTR mode has no single mandated nonce length — the essential requirement is that every 128-bit counter-block input (however a given protocol splits it into a nonce field and a counter field) is unique per key. GCM’s specific construction happens to use a 96-bit nonce plus a 32-bit internal counter, but that’s GCM’s choice, not a generic AES-CTR requirement. When in doubt, prefer a vetted AEAD construction (AES-GCM per its own spec, or AES-GCM-SIV / RFC 8452 for misuse resistance) over hand-rolling raw CTR nonce management. |
| AES-ECB | Structural Pattern Leakage | Independent block encryption (Ci = EK(Pi)) | Plaintext patterns and duplicate blocks remain visible in ciphertext | Do Not Use ECB; deploy AES-GCM or ChaCha20-Poly1305. |
1. ECB Mode: Structural Pattern Leakage
In ECB (Electronic Codebook) mode, every 16-byte plaintext block Pi is encrypted independently using key K:
Ci = EK(Pi)
When identical plaintext blocks occur in input data, identical ciphertext blocks are emitted.
AES-128-ECB block pattern leakage: four identical 16-byte plaintext blocks yield identical 16-byte hex ciphertext outputs (ecb_leak.py)
Client-Side Executable ECB Cryptanalysis Playground
AES-128-ECB Structural Pattern Leakage Playground
Test plaintext block repetition and key conversion directly in your browser (Zero server calls / Executed locally via Web Crypto API).
Chosen-Plaintext & Dictionary Cryptanalysis Attack (ECB Codebook Exploitation)
When a server encrypts data using AES-ECB mode and also exposes an Encryption Oracle (such as a web portal or API endpoint that encrypts attacker-chosen input under the same key K), an adversary can build a Codebook / Dictionary Table mapping candidate plaintexts to their resulting ciphertext blocks — without ever learning K itself.
This is a known-plaintext / chosen-plaintext matching technique, not a general decryption method: a target block is only recovered when the adversary has already guessed its exact 16-byte plaintext and submitted that guess to the oracle. Once a generated ciphertext block matches a block in the stolen target file, that specific block is decrypted by lookup; a block whose true plaintext was never guessed stays opaque no matter how many other candidates are queried:
ECB Codebook Dictionary Cryptanalysis Playground
Simulate an attacker using an Encryption Oracle portal to build a Codebook / Dictionary mapping candidate plaintexts to ciphertexts. Only target blocks whose exact plaintext has already been guessed and submitted will match — this recovers guessed content by lookup, without key K, rather than decrypting arbitrary stolen data.
f443167bd98b197e88e7a6fdc7c01f50de28f66b406a9553e16e0227efff68a11ccee8e0f42d116dc93b77651c4aed13| Candidate Plaintext | Oracle Ciphertext Block (Hex) | Dictionary Match Status |
|---|---|---|
| No candidate plaintexts submitted to dictionary yet. Enter candidate text above. | ||
Because this attack succeeds purely on ciphertext equality, it never decrypts a block outright — it only confirms that a block’s plaintext equals whatever the attacker already guessed and queried through the oracle. A target block encoding an unguessable value (a random session token, for example) will never appear in the codebook and therefore never gets recovered by this method.
2. CBC Mode: Bit-Flipping Malleability & Padding Oracle Attacks
In CBC (Cipher Block Chaining) mode, plaintext block Pi is XORed with previous ciphertext block Ci-1 before encryption:
Pi = DK(Ci) ⊕ Ci-1
Because Ci-1 is XORed directly into decrypted plaintext Pi, altering byte k of Ci-1 changes byte k of Pi by the exact same bitmask, while scrambling block Pi-1 into unrecoverable noise.
Client-Side Executable CBC Bit-Flipping Privilege Escalation Playground
AES-128-CBC Malleability & Privilege Escalation Playground
Demonstrate how altering ciphertext byte 13 in Block 1 flips the exact bit in Decrypted Block 2, forcing isadmin=0 → isadmin=1 without knowing key K (Zero server calls / Executed locally via Web Crypto API).
"user=alice;role=""user;isadmin=0;;" (Target byte: '0' at index 13)isadmin=0 payload).
bc718c55b1a5ff2fae647de3debd047ff3a7ff30057f22130d2d45e041d774f8Because unauthenticated CBC mode lacks an authentication tag (AEAD), decryption succeeds without raising an integrity exception — the tampered plaintext is accepted as valid. Granting unauthorized administrative privileges is this simulator’s chosen scenario, not a property CBC inherently grants; the general lesson is that unauthenticated CBC lets an attacker flip bits in decrypted plaintext undetected, and what that plaintext controls in a real system (an admin flag, a price, a redirect URL) determines the actual impact.
Padding Oracle Attack Mechanics (Vaudenay’s Attack)
A padding oracle is any endpoint that decrypts CBC ciphertext and leaks — via a distinct error message, HTTP status code, or timing difference — whether the resulting PKCS#7 padding was valid. PKCS#7 padding fills the final block so its last n bytes each equal the value n (one padding byte of 0x01, or two bytes of 0x02 0x02, and so on).
Because decryption computes Pi = DK(Ci) ⊕ Ci-1, an attacker who controls Ci-1 can blindly flip any bit of Pi by flipping the corresponding bit of Ci-1 — enough for the bit-flipping attack above — but that alone doesn’t let the attacker set Pi to a chosen value, since DK(Ci) (the intermediate value Ii, before the XOR) is still unknown to them. The padding oracle is what closes that gap: by observing which byte guesses produce valid padding, the attacker recovers Ii one byte at a time, and only once a given byte of Ii is known can they XOR it against any chosen plaintext byte to compute the Ci-1 byte that produces it. The attack recovers a target block Ci working backward from its last byte:
- Replace the last byte of Ci-1 with each of the 256 possible values and resend the (unmodified) Ci to the oracle.
- The guess that yields a valid-padding response reveals the decryption engine’s intermediate value: Ii[15] = guessed_byte ⊕ 0x01 (a single
0x01pad byte is the simplest valid case). - XOR Ii[15] with the original Ci-1[15] to recover the real plaintext byte Pi[15].
- Fix byte 15 so it forces padding
0x02 0x02, then brute-force byte 14 the same way, and continue leftward through the block.
Each byte costs at most 256 oracle queries, so a full 16-byte block falls in roughly 4,096 requests — without ever touching K. This is Vaudenay’s 2002 CBC-padding attack, later automated against real deployments by tools such as PadBuster. The fix is to never let padding validity leak as a distinguishable signal: return a generic error for both MAC and padding failures, keep error handling constant-time, or (preferably) verify a MAC over the ciphertext before attempting decryption (Encrypt-then-MAC), so a tampered ciphertext never reaches the padding check at all.
Encrypt-then-MAC: A Concise Correctness Checklist
If you’re not using a native AEAD construction and are instead composing a cipher with a separate MAC by hand (legacy systems, protocols that predate widespread AEAD support), get these four things right — getting any one wrong reopens some version of the padding-oracle or bit-flipping attacks above:
- Use separate keys for encryption and authentication. Deriving both from the same key (or reusing one key for both roles) risks interactions between the two uses that neither primitive’s individual security proof accounts for — derive two independent keys from a master secret via a KDF (see Key Exchange & Key Derivation).
- Authenticate the ciphertext, not the plaintext — this is what “Encrypt-then-MAC” means, as opposed to MAC-then-Encrypt or MAC-and-Encrypt (encrypting and MACing the plaintext independently). Authenticating post-encryption output is what lets the verifier reject a tampered ciphertext before ever running it through the decryption/padding-removal logic that the Vaudenay attack above exploits.
- Include the IV/nonce and any associated metadata in what’s authenticated, not just the ciphertext bytes — an attacker who can swap the IV while leaving the ciphertext and tag untouched can still manipulate the first decrypted block in CBC-style modes if the IV itself isn’t covered by the MAC.
- Verify the MAC before parsing or decrypting anything, and reject on any mismatch with a generic error, in constant time, before any padding-removal or content-parsing logic runs. Checking the MAC only after decrypting (or only after inspecting the padding) is precisely the ordering mistake that makes the padding-oracle attack above possible.
3. CTR Mode: Nonce Reuse Two-Time Pad Attack
In CTR (Counter) mode, AES operates as a stream cipher, encrypting a counter value to generate a pseudo-random keystream KS:
C1 ⊕ C2 = (P1 ⊕ KS) ⊕ (P2 ⊕ KS) = P1 ⊕ P2
If a nonce is reused under the same key, the exact same keystream KS is generated (KS1 = KS2). XORing two ciphertexts together eliminates the keystream and secret key entirely, leaving the XOR sum of the two plaintexts (P1 ⊕ P2).
Client-Side Executable CTR Nonce Reuse Playground
AES-128-CTR Nonce Reuse Two-Time Pad Playground
Demonstrate how encrypting any two arbitrary messages under the same key and nonce cancels out the AES keystream (C1 ⊕ C2 = P1 ⊕ P2). Type any text in Message 1 and Message 2, then guess a snippet of either message to recover the other!
ECB leaks block-level plaintext patterns, CBC without a MAC is vulnerable to bit-flipping and padding-oracle attacks, and CTR nonce reuse exposes the XOR of two plaintexts. Default to AEAD, or correctly composed Encrypt-then-MAC, instead of an unauthenticated mode.
Primary references
- NIST SP 800-38A: Recommendation for Block Cipher Modes of Operation — NIST CSRC SP 800-38A
- RFC 8452: AES-GCM-SIV: Nonce-Misuse-Resistant Authenticated Encryption — RFC 8452 (IRTF/CFRG Informational)
- OWASP WSTG: Testing for Padding Oracle (Vaudenay’s CBC padding attack) — OWASP Web Security Testing Guide