This is the final test of Wanna.W1n club, somewhere around June 2023
The only Crypto challenge that I solved is AES - CBC related
Description: Login System using authenticated token. Only admin can read the secret!
This is the server.py code:
import json
import os
import signal
from base64 import b64decode, b64encode
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from secret import flag
key = os.urandom(32)
def menu_choice() -> str:
print(
"""Valid choices:
1. Login
2. Register
3. Quit"""
)
return input(">> ").strip()
def handler(_signum, _frame):
print("Time out!")
exit(0)
def encrypt(msg):
iv = os.urandom(16)
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
return iv+cipher.encrypt(pad(msg, 16))
def decrypt(iv, msg):
cipher = AES.new(key, AES.MODE_CBC, iv=iv)
return unpad(cipher.decrypt(msg), 16)
def login():
enc_token = b64decode(input("Login token: ").strip())
print(enc_token)
token = decrypt(enc_token[:16], enc_token[16:])
token = json.loads(token)
print(token)
return token['name'], token['admin']
def register():
name = input("Nickname: ").strip()
token = {
"admin": False,
"name": name
}
token = json.dumps(token).encode()
print(token)
enc_token = b64encode(encrypt(token)).decode()
print("Here is your login token: " + enc_token)
def main():
name = 'N.A'
is_admin = False
print("Welcome to my under-development program. Who are you?")
while True:
choice = menu_choice()
match choice:
case '1':
name, is_admin = login()
break
case '2':
register()
print('')
case '3':
print("Bye bye!")
break
case _:
print("??????????????")
raise RuntimeError("I found a hacker")
if is_admin:
print(f"Hello {name}! Here is your secret: " + flag)
else:
print(f"Hello {name}! Sorry, only admin can read my secret!")
try:
main()
except Exception as E:
print(str(E))
This python code mimics a login system using authenticated token, which is encrypted and decrypted with AES mode CBC, which is the second worst mode just after ECB.
As we can see from the code, it allows us register to generate a token and login using that token. The only catch is that the generated tokens will always have admin = false . If we just register by pressing 2, this will never be solved.
Then we just have to do something, somehow to turn admin=True . This is the part explain why CBC mode is no longer be used.

Looking at the encrypt(msg) and decrypt(msg) we can see that IV is sent with the ciphertext, which is important for us.
Since this is CBC mode and we have IV, then we can perform Bit Flipping Attack.
Remember the is_admin part is at the start of the token? So the ciphertext of that part is also at the beginning of the ciphertext
Let’s divide the plaintext and ciphertext into blocks of 16 byte:
$$ P1,P2,P3,...,Pn $$
$$ C1,C2,C3,...Cn $$
The picture has clearly shown that at the start of decryption, we have
$$ IV ⊕ dec(C1) = P1\\or\\P1 = IV ⊕ dec(C1) $$
where P1 is the part that store is_admin = False .
To turn it into P1’:is_admin = True , we simply do this: