Skip to main content
Cipher Block Chaining (CBC) is one of the most common AES modes you will encounter in web applications, TLS, and CTF challenges. Understanding its construction — and its weaknesses — is fundamental to applied cryptanalysis.

How CBC works

Encryption

Decryption

This chaining has a critical consequence: modifying bytes in ciphertext block C[i-1] predictably flips bytes in plaintext block P[i].

Why CBC is malleable

The decryption formula reveals a direct relationship between the ciphertext and the plaintext of the next block:
Flipping bit j in C[i-1] flips bit j in P[i]. An attacker who knows P[i] can XOR the desired change into C[i-1] to get a chosen P[i]'.

Bit-flip exploit

Scenario: a cookie is formatted as role=user&admin=false, encrypted with CBC, and the server checks the decrypted value.
The block immediately before the target (block target_block - 1) will decrypt to garbage, because its decryption now uses the modified ciphertext as IV. Plan for this side-effect in the exploit.

PKCS#7 padding

AES operates on 16-byte blocks. Plaintext is padded to a multiple of 16 bytes using PKCS#7:
The padding byte value equals the number of padding bytes. A full block of padding (\x10 * 16) is added when the plaintext is already block-aligned. During decryption, the receiver strips the padding and verifies it is valid. If the padding is invalid, many implementations throw an error — creating a padding oracle.

CBC-MAC

CBC-MAC computes an authentication tag as the final output block of CBC encryption with IV=0:
This construction is only secure for fixed-length messages. With variable-length messages, an attacker can forge tags.

Variable-length forgery

Given T1 = CBC_MAC(key, M1) and T2 = CBC_MAC(key, M2):
This works because XOR-ing T1 into the first block of M2 cancels the CBC state, making the computation continue as if it started fresh for M2.

Decrypting with a padding oracle

A padding oracle exists when a system reveals (through error message, HTTP status code, or response time) whether a decrypted ciphertext has valid PKCS#7 padding. This leaks one bit of information per query and is enough to:
  • Decrypt any ciphertext without the key (16 queries per byte, in the worst case 256 each)
  • Encrypt any chosen plaintext (forge ciphertext)
The attack is covered in detail on the Padding Oracle Attacks page.

Common CBC vulnerabilities in the wild

Mitigations

  • Use Authenticated Encryption with Associated Data (AEAD): AES-GCM, AES-GCM-SIV, or ChaCha20-Poly1305. These provide confidentiality and integrity in a single primitive.
  • If CBC must be used, apply encrypt-then-MAC (never MAC-then-encrypt) and use a fresh random IV per encryption.
  • Use constant-time padding validation to eliminate timing oracles.