K3y — Crypto — Digital Cyber Security Hackathon 2023 — Multan Qualifier

Ashar Ahmed
2 min readDec 12, 2023

--

In this challenge, we were provided a Flask application that allowed encrypting user-provided text using AES in counter (CTR) mode with a fixed, unknown key. By interacting with the `/encrypt` route and observing how plaintext encrypts to ciphertext, we can exploit properties of the CTR mode to recover the original flag.

from flask import Flask, render_template, request

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from Crypto.Random import get_random_bytes
from Crypto.Util import Counter
import os


app = Flask(__name__)

KEY = # 32 byte key
import os

FLAG = "flag{test}"

def encrypt_data(txt):
txt = txt.encode('utf-8')
cipher = AES.new(KEY, AES.MODE_CTR, counter=Counter.new(128))
enc_msg = cipher.encrypt(txt)
return enc_msg.hex()



@app.route('/')
def index():
return render_template('index.html')


@app.route('/flag')
def flag():
result = encrypt_data(FLAG)

return render_template('result.html', result=result)


@app.route('/encrypt', methods=['POST'])
def encrypt():
text = request.form['text']

result = encrypt_data(text)

return render_template('result.html', result=result)

if __name__ == '__main__':
app.run(debug=True)

Overview

The provided Flask application has two main functionalities:

- `/flag` — Encrypts a flag and displays the ciphertext
- `/encrypt` — Accepts user input plaintext and displays the ciphertext

The encryption is done using AES in CTR mode, with a fixed 32-byte key that is unknown to us.

The vulnerability lies in the usage of CTR mode with a fixed key. In CTR mode, the keystream used for encryption is solely dependent on the fixed key and initial counter value. This allows us to apply the same keystream to other plaintext/ciphertext pairs encrypted with the same parameters.

Approach

Since the key is fixed, encrypting the same plaintext multiple times would produce the same ciphertext each time.

So our approach is:

1. Submit known plaintext and obtain corresponding ciphertext
2. XOR the ciphertext with the known plaintext to recover the keystream
3. XOR the keystream with the ciphertext for the flag to decrypt it

Exploitation

First, we encrypt a message through `/encrypt` to get a ciphertext:


Plaintext: No right of private conversation was enumerated in the Constitution. I don’t suppose it occurred to anyone at the time that it could be prevented.
Ciphertext: 0f7c08d7137aa480c938fd083d2c16b0efd7b86a5a8c7dcc737444cc3db74107675bb2eec47345475302dc0d1dd79fa450316a21af5c09c7b25053e5739a77d0a2092d

We XOR this ciphertext with the original plaintext to recover the keystream:


key = xor(a, test)

Finally, we take the ciphertext obtained from `/flag`, XOR it with the keystream, and get the flag:

Encrypted flag:

077f49c2014c8fb2a806f56e39102890c8edb1130bb654ca7a5570c5248a1d3b0c7ebec7aa477f020728f9355be8afc143127818bd767eceb07374d429a07599f61b4918df9d20f9264cc42454e69c0d7e434f8e6d890d96a0c7aacc44500340d6a7cffbb7288935368806af1ddfbacd951784d158a5464036f7fe8ce3353778d357eb44c849b097d82f88d20526910468f1

Decrypted flag:

Flag{QCFAQnFtNWVFNlY2UGplSGhmT3RKRmZNQT09OWY2ZTEzM2MzOWJmMTE3Nw==}

By exploiting the fixed key and properties of CTR mode, we were able to decrypt the flag without needing to brute force the key.

#K3y - lmao.py

from pwn import xor

a = bytes.fromhex("077f49c2014c8fb2a806f56e39102890c8edb1130bb654ca7a5570c5248a1d3b0c7ebec7aa477f020728f9355be8afc143127818bd767eceb07374d429a07599f61b4918df9d20f9264cc42454e69c0d7e434f8e6d890d96a0c7aacc44500340d6a7cffbb7288935368806af1ddfbacd951784d158a5464036f7fe8ce3353778d357eb44c849b097d82f88d20526910468f1")
b = bytes.fromhex("0f7c08d7137aa480c938fd083d2c16b0efd7b86a5a8c7dcc737444cc3db74107675bb2eec47345475302dc0d1dd79fa450316a21af5c09c7b25053e5739a77d0a2092d")

test = b"No right of private conversation was enumerated in the Constitution. I don't suppose it occurred to anyone at the time that it could be prevented."

key = xor(a, test)
print(xor(key, b))p

--

--

Ashar Ahmed

Professional investigator of nerdy stuff. Hacks and secures.