Introduction

Pfiou, j'ai enfin fini ce flag provider, on approche de la fin.
TODO:
 * Add IP blocklist in case of spam
 * Ajouter un module de visualisation des flags ratés côté admin
 * Tester le flag provider, et l'ajout de flags en tant qu'admin
 * Tester la feature d'obtention de l'email final
 * Implémenter le get d'email depuis le client lourd (je ne sais pas si j'aurai le temps pour celui llà ...)

Cette dernière étape va nécessiter d’utiliser les fichiers récupérés sur la machine distante de l’étape 3 pour s’interfacer à l’infrastructure du challenge et récupérer l’adresse mail (vu que la fonction n’est pas encore implémentée).

Nuit blanche

Cette dernière étape est, traditionnellement simple, voir triviale. J’y ai passé 3 jours et une nuit blanche. A ne pas comprendre ce qui, dans un code pourtant très simple, pouvait ne pas marcher. Et la morale, c’est que je ne sais pas, mais je remercie, profondément, mes co-challenger pour le soutien morale (ne serait-ce qu’en me disant "mais si c’est ça, ça devrait fonctionner") et ceux qui m’ont supporté pendant cette phase.

Et le pire, c’est que je ne comprends toujours pas pourquoi…​

FlagProvider

Une analyse du code fourni (qui est d’ailleurs plus ou moins identique à celui, paqué, utilisé par le client lourd), nous donne le format des messages permettant de récupérer l’email (module flagprovider).

Un premier message GetFlagsOrder devrait permettre de récupérer une liste ordonnée de flags, et un suffixe. Il faut ensuite dériver un hash (SHA-512) à partir de l’ensemble des flags, le vérifier, si on le souhaite, à l’aide du message FinalEmail. Ce qui nous donne le mail.

Pour accéder à ces messages, il faut posséder un certificat contenant "URL=provider://CHALLENGE_FINISHER" dans les noms additionnels. Il suffit pour ça de posséder un secret, qui est présent dans le fichier conf.toml, et de l’ajouter à son propre fichier de config:

PROVIDER_SECRET = "zOJYJlHrlwPvXHfkTEpLgUXuuIchRYoDHucaohLUUJDBaFZl"

Tout ceci est très simplement faisable à l’aide du code suivant :

with (
        router_addr(),
        router_port(),
    ):
    with default_join('cert2',
            on_received=on_received,
            destination=ProviderID.FLAG_PROVIDER,
            allow_regenerate=False,
            additional_provider_id=ProviderID.CHALLENGE_FINISHER
            ) as (transport, fin):
        print('connect done')
        transport.send(GetFlagsOrder())

Le code de flagProvider contient de nombreux exemples de tests, le dossier MFDProxy (que je n’avais pas récupéré à mon premier passage) un exemple de client.

Ça c’est la théorie. En pratique (╯‵□′)╯︵┻━┻ , le composant sensé générer les certificats ne répond pas, je me prends des erreurs TLS obscures, et je m’enfonce dans des tentatives de debug, modifiant le code du framework, m’injectant dans le client lourd, et globalement en rendant le tout inutilisable. Jusqu’à ce que je me décide de repartir d’une base plus saine, en retournant sur la machine distante pour récupérer, à nouveau, les dossiers flagprovider et MFDClient. Je constate juste que MFDClient fait à priori strictement la même chose que mon code et QUE CA MARCHE PAS.

Mais ça a fini par marcher, un vendredi après-midi.

Flag::FinalEmailSuccess
        SSTICEmail
          76a304cf910e6c6e4051ca7c7c05f8d51fc3e60c4f180077630994484fc9c654_you_deserve_rest@sstic.org
END

Conclusion

Une année un peu particulière pour moi, j’aimerais tout de même remercier les auteurs pour leur travail et pour les puzzles proposés. D’autant plus que j’ai conscience de la difficulté de l’exercice et de la difficulté à créer de nouveaux challenges, après plus de 15 ans. J’ai râlé, je me suis arraché les cheveux sur des problèmes triviaux, j’ai soupiré en voyant des bypass, mais je continue à apprendre, à travers ces challenges. Et pour ça merci, beaucoup.

Comme d’habitude, je remercie aussi mes co-challengers, pour les discussions en attendant que le café coule, pour le soutien morale à des heures indues, pour les moments de joie (ou de frustration) partagés. Et TogGwenn pour toutes ces raisons et plus. Merci et, je l’espère, à l’année prochaine :)


Resource: solve.py

 — Fañch, may 2025