Comment utiliser Nuclei pour rechercher des vulnérabilités dans une application web ?
Sommaire
I. Présentation
Dans cet article, nous allons découvrir et apprendre à maitriser Nuclei : un scanner web, open-source, rapide et puissant. Cet outil peut être utilisé dans de nombreux cas, notamment pour scanner un ou plusieurs sites web très rapidement et découvrir de potentielles vulnérabilités les affectant, et ce, de façon automatisée.
Nuclei propose de très nombreux points de test et de vérification. Par exemple, il vous permettra de facilement découvrir sur des sites web :
- Des fichiers sensibles accessibles ;
- Des signatures spécifiques à certaines technologies, voire la découverte de leur version exacte ;
- Des CVE affectant une application ;
- Des logins par défaut ;
- Des défauts de configuration concernant l'application web, le service web, les en-têtes de sécurité ou les cookies ;
- Des pages d'administration exposées ;
- Réaliser des tâches de fuzzing ;
- Certaines vulnérabilités du top 10 OWASP ;
- Etc.
Et, je ne parle même pas de la prise en compte d'autres protocoles qui peuvent graviter autour de la réalisation d'une analyse de sécurité sur des applications web : DNS, SSH, SSL, mais aussi la réalisation de tâches d'OSINT ou d'analyse de fichiers, etc.
Ce projet open source présent sur le dépôt de ProjectDiscovery possède de nombreuses forces :
- Rapidité : Nuclei est écrit en Go (Golang), un langage notamment optimisé pour le parallélisme et les opérations web/API. Il est capable d'effectuer un grand nombre d'opérations sur plusieurs centaines de sites en relativement peu de temps comparé à d'autres outils.
- Développement communautaire : presque 5 000 commits en 4 ans existences, plus de 300 contributeurs venant de nombreux pays et plus de 8 000 modules de test. La grande force de Nuclei est également sa communauté qui propose continuellement de nouveaux modules de test pour suivre l'actualité des attaques et des vulnérabilités.
- Simplicité de prise en main et de personnalisation : vous le verrez à la fin de cet article, la prise en main de Nuclei est aisé, un peu de pratique sera nécessaire pour une utilisation avancée, mais rien d'insurmontable, il suffit de savoir lire la manpage. Également, les choix techniques faits par les développeurs rendent l'outil personnalisable très facilement grâce au format YAML.
Dans les faits, j'utilise très fréquemment de Nuclei pour automatiser toute sorte de vérification, que ce soit sur une application web précise ou sur plusieurs centaines de sites. Ainsi, les cas d'usage les plus fréquents de Nuclei sont :
- Effectuer une analyse globale d'une surface d'attaque composée de nombreuses applications web ;
- Réaliser un check-up régulier de la sécurité des applications web de son entreprise ;
- Automatiser la vérification de certains points lors test d'intrusion ou d'une recherche Bug Bounty ;
- Vérifier rapidement sur un grand nombre de sites la présence d'une nouvelle vulnérabilité publiée ;
- Etc.
Attention, bien que Nuclei ne soit pas fait pour exploiter des vulnérabilités, il enverra des requêtes qui s'apparenteront quoi qu'il arrive à une cyberattaque. Ainsi, assurez-vous de disposer d'une autorisation explicite des propriétaires des applications web visées (test d'intrusion, analyse interne à l'entreprise ou Bug Bounty). Pour rappel : Code pénal : Chapitre III : Des atteintes aux systèmes de traitement automatisé de données
II. Installation de Nuclei
Nous allons à présent installer Nuclei, j'utilise pour cela un OS Linux (Kali Linux), mais cela devrait fonctionner sur n'importe que Système Linux. L'outil étant écrit en Go, votre système doit disposer de quoi exécuter les programmes écrit en Go, vous pourrez vérifier que c'est le cas via la commande suivante :
$ go version
go version go1.21.6 linux/amd64
Si vous n'avez pas une version en réponse, c'est que Go n'est pas présent sur votre système. Je vous oriente vers la documentation officielle, très claire, pour l'installer :
Pour que Nuclei puisse être utilisé depuis n'importe quel dossier de votre système, n'oubliez pas d'ajouter le répertoire dans lequel seront stockés les binaires Go dans votre variable "PATH" et d'intégrer cette modification à votre ".bashrc" :
export PATH=$PATH:/usr/local/go/bin
Une fois cela fait, nous pouvons installer Nuclei avec la commande suivante :
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
Pour vérifier qu'il s'est bien installé, vous pouvez utiliser la commande suivante :
nuclei --version
Si tout s'est bien passé, voici le résultat attendu :
L'outil étant très souvent mis à jour, cette commande vous permettra également de mettre à jour Nuclei. Pour finir, il faut nous assurer que notre base de templates, nom des modules de test de Nuclei, est à jour. Nous pouvons pour cela utiliser la commande suivante (-ut" pour "--update-templates") :
nuclei -ut
Voici une sortie possible :
Voilà, notre base est à jour. Pensez à mettre souvent à jour votre base de template, car de nouveaux sont très souvent disponibles.
II. Maitriser Nuclei pour scanner des sites web
A. Utilisation basique de Nuclei
À présent, nous allons commencer à utiliser Nuclei dans des cas basiques, afin de se faire la main. Pour commencer, nous pouvons lancer Nuclei en mode "par défaut", sans trop lui spécifier d'option. Nous devons au moins lui spécifier l'application web à scanner :
Comme vous pouvez le voir, nous obtenons quelques informations à propos du contexte de lancement du test. Nous voyons notamment si Nuclei et notre base de template sont à jour, mais aussi le nombre de templates qui seront utilisés ici : 7921.
En sachant qu'un template peut lui-même exécuter plusieurs requêtes, cela donne une idée du nombre de requêtes et de tests que Nuclei va faire.
Vu l'application web testée ici, je ne suis pas près de trouver des vulnérabilités là-dessus avec Nuclei. Mais c'est pour l'exemple :). Vous noterez tout de même que Nuclei me renvoie quelques alertes de type "[info]", qui correspondent à des points de vérifications standard (certificat, CDN utilisé, technologies, etc.).
Pour connaitre le nombre exact de requêtes qui seront envoyées, et en plus avoir un état d'avancement du test, je vous conseille de systématiquement utilisé l'option "--stats" :
nuclei -u https://monapplication.tld --stats
Voici ce que cette option va changer :
Vous aurez un suivi, toutes les 5 secondes, du nombre de tests fait et à faire, le nombre d'hôtes qui ont été scannés parmi ceux fournis en entrée, le nombre de template pour lesquels il y a eu un résultat (4 dans mon exemple) et le nombre d'erreurs. Ce dernier nombre sera forcément élevé puisque la plupart des tests n'aboutiront pas, la cible ne pouvant de toute façon pas être vulnérables à tout d'un seul coup :-).
Pour aller plus loin, nous pouvons aussi scanner non pas une application web, mais un nom de domaine, observons la différence :
Comme vous pouvez le voir, Nuclei va utiliser "httpx" sur le nom de domaine fournit. Cet outil tiers va permettre de déterminer quels sont les services web accessibles sur le nom de domaine en allant vérifier sur les ports classiques pour ce service : TCP/80, TCP/81, TCP/443, TCP/8080, etc. Cela permet de faire une analyse un peu plus large, et de scanner aussi bien le service TCP/443 que les TCP/8080 si les deux sont présents pour un même domaine.
Enfin, dans un contexte plus réaliste, nous pouvons scanner plusieurs applications web, domaine ou adresse IP. Il suffit pour cela de créer un fichier texte avec une cible par ligne et d'indiquer ce fichier à Nuclei :
nuclei --list mesCibles.txt --stats
Voilà pour l'utilisation vraiment basique de Nuclei. Peut-être avez-vous déjà eu des premiers résultats ici, mais je vous conseille de continuer la lecture de l'article, car nous allons apprendre à manier l'outil de façon beaucoup plus efficace et intéressante.
B. Découverte et usage des templates
Comme indiqué dans l'introduction, la puissance de Nuclei réside dans ses nombreux templates et son approche modulaire. Les templates de Nuclei décrivent chacun un test bien précis et ceux-ci sont organisés en catégories et en tags, ce qui permet de facilement les utiliser en fonction de nos besoins. Voici notamment un aperçu des tags les plus présents :
Vous trouverez sur la page suivante la totalité des tags pouvant être utilisés dans les options d'exécution de Nuclei :
Par défaut, vos templates Nuclei sont normalement stockés dans le répertoire "~/.local/nuclei-templates/". Vous pourrez également les parcourir dans ce répertoire local.
Commençons, pour se faire une idée, par afficher tous les templates disponibles grâce à l'option "-tl" :
Comme vous pouvez le voir, il y a du monde ! Pas loin de 8 000 templates sont disponibles en date d'écriture de cet article. La capture ci-dessus est bien sûr tronquée. On peut notamment retrouver un début de hiérarchie dans la capture ci-dessus (cloud, code, exposures, etc.). Pour avoir une meilleure idée, voici à quoi ressemble un template Nuclei :
Voir le template sur Github :
Ce template, qui se trouve dans le répertoire "http/exposed-panels/" et utilise les tags "panel" et "phpmyadmin" (ligne 17) a pour but de découvrir la présence d'une page d'authentification ou d'un panel "PHPMyAdmin" sur nos cibles.
Nous pouvons notamment voir les payloads qui seront utilisés sur chaque cible, il y en a ici 12. Ce qui signifie que ce test à lui seul générera 12 requêtes par cible. En exécutant ce test, Nuclei essaiera de charger la page "{{baseURL}}/phpmyadmin/" puis "{{baseURL}}/admin/phpmyadmin/", etc. Le "{{BaseURL}}" étant bien sûr remplacé à la volée par l'URL des applications ciblée par nos tests.
Pour chaque réponse, il consultera le code source de la page afin de trouver les chaines de caractères "phpMyAdmin" ou "pmahomme" et lèvera une alerte de niveau "[info]" s'il obtient une réponse positive.
Pour exécuter une analyse se basant sur ce template uniquement, nous pouvons utiliser la commande suivante :
nuclei -t http/exposed-panels/phpmyadmin-panel.yaml -list mesCibles.txt -stats
Ici, Nuclei va automatiquement aller cherche le fichier ".yaml" au sein du répertoire par défaut de stockage des templates. Si nous souhaitons utiliser un ensemble de template en fonction de leur catégorie, nous pouvons utiliser la commande suivante :
# Templates relatifs à la découverte de panels d'administration
nuclei -t http/exposed-panels/* -list mesCibles.txt -stats
# Templates relatifs à la découverte de technologies et version
nuclei -t http/technologies/* -list mesCibles.txt -stats
Nous pouvons également nous aider des tags, qui permettent de sélectionner des templates dans plusieurs catégories. Par exemple, si nous avons un CMS "Joomla" à scanner, nous pourrions souhaiter découvrir ses plugins, sa version, puis la présence de CVE ou défauts de configuration spécifiques à "Joomla". Chacun de ces tests se trouve dans une catégorie Nuclei différente, mais tous partagent le même tag : "joomla". Exemple :
# Lister les tous les templates ayant un tags "joomla"
nuclei -tl --tags joomla
# Exécuter tous les templates ayant un tags "joomla"
nuclei --tags joomla -list mesCibles.txt -stats
L'utilisation unitaire d'un template, groupée via les tags ou via les catégories, est ce qui rend Nuclei très pratique d'utilisation et modulable en fonction des besoins et des cibles à scanner. Le grand nombre de templates et de modules nécessite quelque temps de pratique avant de pouvoir exploiter complètement la puissance de Nuclei, mais cela vaut vraiment le coup.
Nuclei est un outil très modulable et propose, en plus de ses nombreux templates, de nombreuses options. Prenez le temps de lire l'aide de l'outil pour avoir un aperçu de tout ce qu'il est capable de faire : "nuclei --help"
Également, plutôt que de réaliser une analyse soit trop précise, soit trop vague entrainant un grand nombre de requêtes inutiles. Nous pouvons utiliser le mode "intelligent" de Nuclei qui va utiliser l'application wappalyzer afin de réaliser une première découverte des technologies utilisées, puis un scan en utilisant les tags associés à ces technologies. Cette opération se fait via le tag "-as" (pour "-automatic-scan") :
# Analyse intelligente basée sur le détecteur de technologie wappalyzer
nuclei -as -list mesCibles.txt -stats
Avec ces quelques options, vous maitriserez mieux les différents concepts et la puissance de Nuclei. Pour vous faciliter l'utilisation des tags, je vous propose ce tableau qui détaille, pour les principaux tags, leur cas d'usage :
Tag | Usage |
--tags cve, --tags cve2023, --tags cve2022 | Templates relatifs à la détection de CVE. Utilisable aussi par année. |
--tags panel | Templates permettant de découvrir des panels d'administration spécifiques à certaines technologies. |
--tags wordpress, --tags wp-plugin, --tags joomla, etc. | Templates relatifs aux CMS, ou à la découverte de plugins des CMS. |
--tags exposures | Templates permettant de rechercher des fuites de données dans des fichiers exposés (backups, configurations, etc.) |
--tags osint | Templates relatifs à la recherche d'informations par sources ouvertes. |
--tags tech | Templates de recherche de bannières des technologies utilisées et de leurs versions. |
--tags misconfig | Templates permettant de rechercher des défauts de configuration classiques et connus dans les services web, les CMS, etc. |
IV. Concevoir son propre template
A. Comprendre la structure d'un template
Nous allons à présent étudier un peu plus précisément les différents composants d'un template afin d'avoir les connaissances nécessaires pour construire notre premier template.
Vous l'autre peut être remarqué en manipulant Nuclei ou en lisant cet article, les templates Nuclei sont écrits en YAML et visent à décrire précisément comment les requêtes seront envoyées et leurs réponses analysées. On retrouve d'ailleurs l'utilisation du YAML dans les règles de détection SIGMA. Voici la structure globale d'un template :
- Identifiant unique
C'est le nom du template, il sera utilisé notamment lors de l'affichage d'une alerte :
id: mon-premier-template
- Les informations de métadonnées
Les "info" sont les données annexes d'un template, comme l'auteur, la description, mais aussi les tags, le niveau de criticité de l'alerte qui sera levée, etc. Elles sont importantes pour bien réutiliser, comprendre et évaluer les résultats de notre template par la suite.
info:
name: Mon premier template
author: it-connect
severity: medium
description: Je ne sais pas encore
reference: https://www.it-connect.fr
tags: generic
- Le protocole ciblé et la requête
Comme indiqué, bien que Nuclei s'oriente principalement autour du web (HTTP), il peut aussi faire quelques actions sur d'autres protocoles comme SSH, DNS, ou directement sur des fichiers. C'est aussi là que sera décrite la requête à envoyer, avec sa méthode (dans le cas de l'HTTP), les données POST, le chemin ciblé, le tout en utilisant des variables comme "{{BaseURL}}", comme vu plus haut.
Voici un exemple du module "tomcat-exposed-docs.yaml"
http:
- method: GET
path:
- '{{BaseURL}}/docs/'
- Les matchers
Les matchers sont les éléments principaux du template, ils permettent d'analyser la réponse obtenue et d'y rechercher des éléments indiquant le succès de l'opération. Il s'agit en fait de différentes conditions pouvant s'appliquer sur les en-têtes de réponse, le corps de la réponse, son statut, sa taille, etc. Il est alors possible d'indiquer si toutes les conditions doivent être remplies pour déterminer un succès, ou seulement certaines d'entre elles. Ce sont notamment ces conditions qui assurent un minimum de faux positif.
Voici un exemple du template "tomcat-exposed-docs.yaml" :
matchers-condition: and
matchers:
- type: word
words:
- 'Apache Tomcat'
condition: and
- type: status
status:
- 200
Dans l'exemple ci-dessus, les conditions sont à la fois la présence de "Apache Tomcat" dans le corps de la réponse, et l'obtention d'un code HTTP 200 en retour.
- Les extractors
Les extractors sont optionnels et sont déclenchés uniquement en cas de succès du test. Ils permettent de récupérer des informations supplémentaires comme une version grâce à une expression régulière.
Voici un exemple du module "tomcat-exposed-docs.yaml" :
extractors:
- type: regex
part: body
group: 1
regex:
- '<div class="versionInfo">[ \n\t]*(Version[ \n\t]*[^\n\t<]+)[ \n\t]*<time'
B. Recherche d'un fichier ou d'un répertoire
Maintenant que nous connaissons la structure globale d'un template. Nous pouvons construire notre premier templates. Nous ferons simple pour débuter.
Supposons que nous avons découvert que l'administrateur système qui a été embauché pour l'été afin d'effectuer une sauvegarde de nos nombreuses applications web n'a pas été très rigoureux et a laissé certaines de ces archives "backup-lesysadmin.zip" à la racine des applications web. Notre entreprise possédant 340 serveurs web en DMZ avec plusieurs dizaines d'applications chacun, toutes dans des répertoires différents, il serait aussi rapide d'utiliser Nuclei pour aller identifier la présence de ce fichier sur toutes nos applications web.
Pour répondre à ce besoin, il faut commencer par définir les métadonnées de notre template :
id: recherche-zip-sysadmin
info:
name: Recherche archive ZIP du Sysadmin
author: it-connect
severity: medium
description: Recherche de l'archive ZIP créée par notre Sysadmin cet été
reference: https://www.it-connect.fr
tags: generic
Nous allons ensuite définir la requête à envoyer et les conditions à réunir pour déterminer le succès de l'opération. Ici, un code "200" et un en-tête "Content-Type" à "application/zip" :
http:
- method: GET
path:
- '{{BaseURL}}/backup-lesysadmin.zip'
matchers:
- type: word
part: header
words:
- 'application/zip'
condition: and
- type: status
status:
- 200
Notre premier template est prêt ! Pour l'utiliser, il suffit de spécifier le chemin vers le fichier à l'aide de l'option "-t", comme vu précédemment. Voici le résultat :
Nous avons bien un match sur l'une de nos applications web. L'alerte est, comme prévu, remonté en sévérité "Medium".
En cas de problème, notamment si Nuclei fait mine de ne pas avoir de template à utiliser, je vous conseille d'utiliser l'option "-v", les éventuelles erreurs de votre template seront alors affichées :
Si vous souhaitez développer d'autres templates pour effectuer des tâches différentes ou plus complexes, je vous conseille de partir d'un template existant qui fait à peu près la même opération. Qu'il s'agisse de l'envoi de données en POST, la récupération d'informations dans les en-têtes ou le corps de la requête, etc. Vous aurez ainsi une base concrète sur laquelle démarrer.
V. Quelques options pour maitriser la bête
Je vous propose différentes options pour maitriser un peu plus la puissance de Nuclei. Il s'agit des options dont je me sers le plus au quotidien et qui sont, selon moi, utiles à connaitre pour une utilisation plus régulière de l'outil :
- Générer un fichier de sortie
Pour stocker, archiver, comparer ou même traiter les données produites par Nuclei, il peut être utile d'écrire ses résultats dans un fichier. Nuclei propose notamment le format de sortie JSON, un format standard pouvant être facilement réutilisé par d'autres outils ou langage de programmation :
# Sortie texte standard
nuclei -list mesCibles.txt -o nuclei_output.txt
# Sortie au format JSON
nuclei -list mesCibles.txt -j -o nuclei_output.json
- Gérer le nombre de requêtes sur une période
Vous constaterez surement rapidement que Nuclei et un outil très rapide, il peut arriver que les services web ou équipements intermédiaires aient du mal à encaisser la charge ou bannisse votre adresse IP si elle émet trop de requêtes sur une courte période. Pour cela, Nuclei intègre une option permettant de gérer le nombre de requêtes par seconde :
# Limiter l'exécution à 50 requêtes/seconde (valeur par défaut : 150)
nuclei -list mesCibles.txt -rl 50
- Sélectionner/exclure les template exécutés par criticité
La sortie produite par Nuclei peut vite être très verbeuse en fonction du type, de la maturité et du nombre de cibles. Ainsi, de nombreuses options permettent de mieux contrôler les tests qui seront effectués et notamment d'en inclure ou omettre en fonction de la criticité de chaque template, établie sur 6 niveaux : unknown, info, low, medium, high, critical :
# Exécuter uniquement les templates à criticité medium, high et critical
nuclei -list mesCibles.txt -s medium,high,critical
# Exclure des tests les templates high et critical
nuclei -list mesCibles.txt -es high,critical
- Optimiser la vitesse de tests
Il est aussi possible d'utiliser certaines options pour que la durée des tests soient optimisée. Par exemple, en raccourcissant le temps ou le nombre de requêtes à partir desquels Nuclei considère une page ou hôte en injoignable/timeout, ou le nombre de tentatives supplémentaires qu'il va faire après un premier échec :
# Réduire le nombre de seconde avant de requête en timeout (par défaut : 10
nuclei -list mesCibles.txt -timeout 2
# Réduire à 3 au lieu de 30 le bombre d'échec avant de considérer un hôte définitivement injoignable
nuclei -list mesCibles.txt -mhe 3
# Réduire à 1 au lieu de 3 le nombre de tentative de communication après un échec
nuclei -list mesCibles.txt -retries 1
Ces différentes options peuvent bien sûr être combinées entre elles pour plus d'efficacité.
VI. Conclusion
Dans cet article, nous avons fait le tour des principales options et cas d'usage de Nuclei. Cela devrait vous permettre de l'utiliser dans de bonnes conditions, bien qu'il regorge de fonctionnalités dont nous n'avons pas parlé grâce à ses nombreuses options et templates. J'espère notamment qu'utiliser cet outil vous aidera à trouver et à corriger des faiblesses sur vos applications web pour améliorer votre sécurité !
N'hésitez pas à donner votre avis dans les commentaires ou sur notre Discord !
ça peux être intéressant pour scanner si le matos qu’on vends possède des cve connues, je testerais à l’occaz…
Hello ! Très bon article, hâte de tester la solution qui a l’air particulièrement performant
PS : petite coquille sur la section « -as », tu as recoller le code pour le tag joomla 😀
C’est corrigé, merci 🙂