Voici ma solution pour le challenge Cornelius 1 du Hack.lu CTF, auquel j'ai participé avec la team 0x90r00t.

Vous pouvez trouver la source du challenge dans mon dépôt.

Ici, le problème est que l'on compresse les données avec deflate avant de les chiffrer avec un mode CTR. On peut donc utiliser une attaque du même principe que CRIME, pour deviner petit à petit le flag.

En effet, lorsque plusieurs chaînes de caractères se répètent, l'algorithme deflate utilise ces répétitions pour diminuer la taille des données compressées.

Le serveur nous renvoit le résultat de :

CTR(deflate("[username, flag:"flag=le_flag_a_deviner"]"))

Puisque l'on contrôle complétement la chaîne username, lorsque l'on reçoit des données plus courtes que d'autres on peut donc deviner que notre chaîne utilisateur se répète dans le flag, et récupérer petit à petit tous les caractères de ce dernier.

Voici l'exploit final :

import urllib.request
import binascii
import base64

URL = "https://cthulhu.fluxfingers.net:1505/?user=%s"

def get_cookie(url, user):
    url = url % urllib.parse.quote(user)
    d = urllib.request.urlopen(url)

    return base64.b64decode(d.getheader('Set-Cookie')[5:])

charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_:{}"

def bf(flag):

    print(flag)

    lengths = {}

    for c in charset:
        l = len(get_cookie(URL, (flag + c + "-") * 10))

        if l not in lengths:
            lengths[l] = [c]
        else:
            lengths[l].append(c)

    keys = sorted(lengths.keys())

    if len(keys) > 1:
        for c in lengths[keys[0]]:
            print("Candidates: %s" % lengths[keys[0]])
            bf(flag + c)

bf('flag:')