$ cat writeup.md…
$ cat writeup.md…
fortid2026
Task: networked PyCryptodome vault encrypts secrets with AES-CTR but derives the CTR nonce from the plaintext's first 8 bytes under a fixed per-session key. Solution: exploit keystream reuse (two-time pad) by submitting chosen plaintexts that share the flag's 8-byte prefix, brute-force the unknown 8th byte via ciphertext-prefix collision, then XOR-recover every flag byte against a long chosen plaintext.
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
Safely Store a Secret Value. A networked "secret vault" lets you store secrets and export the stored ciphertexts. The flag is pre-loaded as the first vault entry.
English summary: A TLS-wrapped ncat service (port 1337) runs a Python/PyCryptodome vault. Options: (1) store a secret, (2) export all ciphertexts as hex JSON, (3) exit. The flag is auto-inserted as Secret #0 at startup. A 15-second SIGALRM limits each session. Goal: recover the flag (FortID{...}).
The cipher class is the whole vulnerability:
class Cipher: def __init__(self): self.key = get_random_bytes(16) # fixed for the whole session def encrypt(self, plaintext): cipher = AES.new(self.key, AES.MODE_CTR, nonce=plaintext[:8]) return cipher.encrypt(plaintext)
Key observations:
insert.plaintext[:8] — attacker-controlled and, crucially, identical whenever two plaintexts share their first 8 bytes.ct[i] = pt[i] XOR ks[i], where the keystream ks depends only on (key, nonce).Therefore the keystream depends only on (key, first 8 bytes of plaintext). Any two plaintexts beginning with the same 8 bytes get the same keystream — a classic two-time pad / keystream-reuse situation.
The flag's prefix is partially known: FLAG.startswith("FortID{"), so bytes 0–6 are "FortID{". Only the 8th byte (index 7) is unknown, and it is drawn from a small printable charset. The export option leaks every ciphertext including Secret #0 (the flag), so we can compare ciphertexts directly.
...
$ grep --similar