Challenge example
Source code
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import json
import os
FLAG = ?
KEY = ?
def encryptFlag():
data = {"flag": FLAG}
plaintext = json.dumps(data).encode()
padded = pad(plaintext, 16)
iv = os.urandom(16)
cipher = AES.new(KEY, AES.MODE_CBC, iv)
try:
encrypted = iv + cipher.encrypt(padded)
print(f"Here is your token : {encrypted.hex()}")
except ValueError as e:
print({"error": str(e)})
return
def checkToken():
token = input("Token : ")
token = bytes.fromhex(token)
iv = token[:16]
token = token[16:]
cipher = AES.new(KEY, AES.MODE_CBC, iv)
try:
plaintext = cipher.decrypt(token)
unpadded = unpad(plaintext, 16)
data = json.loads(unpadded)
except ValueError as e:
print({"error": str(e)})
return
if data["flag"] == FLAG:
print("Token is valid")
print("Welcome !")
encryptFlag()
checkToken()The objective is to break the ciphertext to retrieve the flag value.
Exploitation
Vulnerability detection
In order to exploit the padding oracle attack, there are 2 things that need to be checked:
We can send as many time as we want a ciphertext to decrypt.
The application returns an error in case of padding error.
POC
As explained here, in order to retrieve the last character of the last block, we need to brute force the last character of the penultimate block until the application returns a valid padding.
Then the real plaintext byte will be bruteforce_result ⊕ original_block_byte ⊕ 0x01
Full exploitation
We just have to update the code to make it follow the entire padding oracle algorithm
Using Libraries
Many people have write libraries to automate this attack. Here is an example using this python implementation of padBuster :
Exercice
If you want to try this exploit by yourself, you can pull this docker image :
Deploy the image using the followed command :
The service is available on port 1337
Last updated