AES-CBC Bit Flipping Attack
Last modified: 2023-09-07
Bit Flipping Attack is an attack to change to result in a predictable change of the plaintext by making bitwise changes to ciphertext
How It Works
Here is an CTF example.
Assume that a plaintext and ciphertext pair as follow.
# plaintext
logged_username=admin&parsword=aNth3m2023&password=g0ld3n_b0y
# ciphertext generated from the plaintext
f9d300b808e4c5ab535bc2c71600b58c328d2dc808ffa98740253a9f1fd905a05ddc53999f7f515427212aad1ea8831d2833732d29529899a0ec964c2f23fb58
Usually, CBC (Cipher Block Chaining) mode encrypts a plaintext every 16 bytes after XORing with the previous ciphertext. By the way, the first block of the plaintext is XORed with IV (initialization vector, generated random 16 bytes). Below depicts the process.
Encryption Process
# Block 1
ENCRYPT(logged_username= ^ IV)
# ciphertext 1
f9d300b808e4c5ab535bc2c71600b58c
# Block 2
ENCRYPT(admin&parsword=a ^ f9d300b808e4c5ab535bc2c71600b58c)
# ciphertext 2
328d2dc808ffa98740253a9f1fd905a0
# Block 3
ENCRYPT(Nth3m2023&passwo ^ 328d2dc808ffa98740253a9f1fd905a0)
# ciphertext 3
5ddc53999f7f515427212aad1ea8831d
# Block 4
ENCRYPT(rd=g0ld3n_b0yxxx ^ 5ddc53999f7f515427212aad1ea8831d)
# ciphertext 4
2833732d29529899a0ec964c2f23fb58
Decryption Process
We can reverse the above process as below. Decrypted ciphertext is XORed with the previous ciphertext every 16 bytes.
# Block 1
DECRYPT(f9d300b808e4c5ab535bc2c71600b58c) ^ iv
# plaintext 1
logged_username=
# Block 2
DECRYPT(328d2dc808ffa98740253a9f1fd905a0) ^ f9d300b808e4c5ab535bc2c71600b58c
# plaintext 2
admin&parsword=a
# Block 3
DECRYPT(5ddc53999f7f515427212aad1ea8831d) ^ 328d2dc808ffa98740253a9f1fd905a
# plaintext 3
Nth3m2023&passw
# Block 4
DECRYPT(2833732d29529899a0ec964c2f23fb58) ^ 5ddc53999f7f515427212aad1ea8831d
# plaintext 4
rd=g0ld3n_b0yxxx
Exploitation: Creating Fake Plaintext
In the previous CTF example, we can get the original plaintext by changing the value at the position of 'r' in the 'parsword' on the ciphertext to XORed value,. It does not affect other blocks. Extracting that part:
# Block 2 (change 53 -> 52 at the 9th byte)
DECRYPT(328d2dc808ffa98740253a9f1fd905a0) ^ f9d300b808e4c5ab 52 5bc2c71600b58c
# plaintext 2 (changed 'r' to 's' at the 9th byte)
admin&password=a
Exploitation: Creating Fake IV
Reference: https://cryptohack.org/courses/symmetric/flipping_cookie/
To create a fake IV which triggers to generate a fake plaintext (e.g. "admin&password=a") at the first block, we can abuse the XOR mechanism.
Since elements can be replaced each other in XOR, we can calculate a fake IV as below.
iv = ciphertext[:16]
plaintext = "admin=False&expi"
fake_plaintext = "admin=True&expir" # Add 'r' at the end to adjust 16-bytes for correct padding
DECRYPT(block1) = plaintext ^ iv
# We can replace each element: `iv = DECRYPT(block1) ^ plaintext`
fake_iv = DECRYPT(block1) ^ fake_plaintext
fake_ciphertext = fake_iv + ciphertext[16:]