Décryptage du CTF Fetch the Flag 2022 : Pay Attention
Assaf Ben Josef
10 novembre 2022
0 minutes de lectureMerci d’avoir participé à Fetch avec nous ! Félicitations aux milliers de joueurs qui nous ont rejoints pour Fetch the Flag CTF. Et un immense merci aux Snykers qui ont créé, testé et documenté les défis !
Dans cet article, nous allons voir comment notre équipe a abordé le défi pay-attention du CTF Fetch the Flag 2022 de Snyk. Ce défi simule une situation où un paquet populaire a probablement été détourné et rendu malveillant. Nous allons nous mettre dans la peau de la personne chargée de la recherche en sécurité qui enquête sur le problème !
Guide pas à pas
Au lancement, un fichier téléchargeable nous est proposé : pytest-7.1.3.tar.gz, accompagné de l’indice « Avez-vous été attentif récemment ? ».
D’emblée, le nom du fichier nous interpelle. Pytest est un framework de test Python très populaire et, à l’heure où nous écrivons ces lignes, la version 7.1.3 est la plus récente. Il semble donc que ce fichier soit une archive de la dernière version de pytest.
Il ne peut certainement pas s’agir d’une copie conforme de la véritable version 7.1.3 de pytest, sinon nous n’aurions aucun indice à exploiter ! Pour le vérifier, nous allons consulter le dépôt GitHub de pytest et télécharger le code source de la version 7.1.3. En examinant les propriétés de ces archives, nous constatons que la version de pytest du CTF est légèrement plus volumineuse que la version originale.
Pour trouver précisément où se situe la différence entre ces deux archives, nous pouvons extraire les dossiers et les comparer à l’aide de la commande diff -rq dans le terminal. Celle-ci parcourt récursivement le contenu des dossiers à la recherche de différences entre les fichiers, comme ceci :

Nous trouvons quelques différences mineures dans certains fichiers de métadonnées. Mais surtout, l’un des fichiers de code source proprement dits, fixtures.py, diffère entre les deux dossiers : nous tenons notre piste !
Repérer le code suspect
En examinant le fichier dans notre IDE préféré et en le parcourant un moment (ou en laissant l’IDE nous signaler une indentation inattendue), nous repérons cette ligne de code suspecte :
À première vue, cette ligne semble importer des bibliothèques, puis appeler des fonctions intéressantes, comme b64decode et exec. C’est clairement suspect, mais nous ne savons pas encore vraiment ce qui se passe. Décodons tout ça.
Nous allons commencer par les chaînes les plus courtes qui suivent un motif similaire, comme \x65\x78\x65\x63.
Certains savent peut-être que Python 3 utilise Unicode pour représenter les chaînes de caractères. En approfondissant la documentation de Python 3, nous découvrons que ce motif correspond simplement à la représentation hexadécimale à deux chiffres des points de code Unicode.
Mais, en réalité, nous n’avons pas besoin de tout savoir cela. En observant la ligne de code, nous voyons que ces chaînes sont transmises telles quelles à des fonctions intégrées de Python, comme __import__(). Nous pouvons donc supposer que l’interpréteur Python sait déjà les traiter. En lançant un REPL Python, nous pouvons appeler la fonction print() avec n’importe laquelle de ces chaînes pour afficher leur représentation Unicode lisible. Par exemple, print(‘\x65\x78\x65\x63’) renverrait la chaîne exec. Pratique !
Une fois tout cela décodé, nous obtenons le résultat suivant :
Il semble que ce script décode une chaîne en base 64, la compile, puis l’exécute. Nous voulons maintenant savoir quel morceau de code est exécuté. Décodons donc cette chaîne en base 64 à l’aide d’un outil de décodage en ligne. Voici ce que nous obtenons :
Cette fois, le code semble créer un fichier temporaire, y écrire un court script, puis l’exécuter. Le script contenu dans ce fichier temporaire télécharge et exécute un morceau de code depuis une ressource en ligne (sur le domaine du CTF de Snyk).
Nous voulons suivre les indices jusqu’au bout pour découvrir quel morceau de code est finalement exécuté dans cette chaîne, mais nous nous heurtons à un obstacle de taille. Le code téléchargé est complètement obscurci ! La seule partie compréhensible se trouve tout en haut : elle nous indique le nom et le dépôt GitHub de l’outil utilisé pour obscurcir le code, Hyperion.
Notre premier réflexe pourrait être de nous dire que, puisque nous avons le script obscurci et le code source de l’outil d’obfuscation, il nous suffit de retrousser nos manches et de faire de la rétro-ingénierie. Cependant, comme ce script semble très bien obscurci et que le fichier README du dépôt GitHub de l’outil indique qu’aucun outil de désobfuscation n’est disponible pour le moment, nous avons décidé d’épuiser d’abord toutes les autres pistes.
Dans cette optique, nous avons commencé par télécharger le script obscurci dans un fichier local, puis par configurer un environnement de débogage pour voir si nous pouvions repérer quelque chose d’intéressant à l’exécution. Dans notre IDE préféré, nous pouvons déboguer et exécuter ce code ligne par ligne afin de surveiller ce qui se passe.
Avertissement de sécurité
Dans une situation réelle, si nous avions affaire à un script conçu pour causer des dommages, nous effectuerions toutes ces opérations dans un environnement sandbox sécurisé !
Heureusement, notre œil finit par repérer le flag dissimulé parmi les variables déclarées (après avoir supprimé les barres obliques inverses) :

Vous avez été attentif !
Pour récapituler, nous avons trouvé :
Un paquet qui semblait inoffensif, mais dont l’un des fichiers contenait une ligne de code suspecte
Cette ligne de code compile et exécute un script encodé en base 64
Ce script crée et exécute un fichier temporaire
Ce fichier accède à une ressource distante pour télécharger un script obscurci, puis l’exécute
En examinant et en déboguant ce script obscurci, nous avons finalement trouvé le flag dissimulé parmi ses déclarations.
Ce type d’obfuscation à plusieurs niveaux est très courant dans les injections de scripts malveillants. Quelle aventure !
Vous voulez savoir comment nous avons trouvé tous les autres flags ? Consultez notre page solutions de Fetch the Flag pour découvrir comment nous avons procédé.



