Zeecka zeecka

// article

Outils d'énumération de contenu web en 2021

Benchmark des outils d'énumération de contenu web disponibles en 2021

Outils d’énumération de contenu web

Résumé

Note : l’article original a été publié sur le blog de mon entreprise https://blog.sec-it.fr/.

La découverte du périmètre est une étape importante lors d’un pentest web et peut, dans certains cas, mener à la compromission d’un site web. Afin de réaliser cette reconnaissance, plusieurs outils sont disponibles, notamment les outils d’énumération de contenu web :

NomVersion*Première releaseDernière releaseLangage
Dirb2.222005/04/272014/11/19C
DirBuster1.0-RC120072013/05/01Java
Dirsearch0.4.12014/07/072020/12/08Python3
FFUF1.2.12018/11/082021/01/24Go
Gobuster3.1.02015/07/212020/10/19Go
Wfuzz3.1.02014/10/232020/11/06Python3
BFAC (Bonus)1.02017/11/082017/11/08Python3

* cet article a été rédigé en février 2021

D’autres outils comme Rustbuster, FinalRecon ou Monsoon existent et ne seront pas décrits en détail car ils sont moins connus et utilisés. Ils figureront dans la synthèse.

Dirb

Dirb est un scanner de contenu web écrit en C et fourni par The Dark Raver depuis 2005.

DIRB est un scanner de contenu web. Il recherche des objets web existants (et/ou cachés). Il fonctionne essentiellement en lançant une attaque par dictionnaire contre un serveur web et en analysant la réponse.

La dernière release de cet outil remonte à 5 ans, en 2014, avec la version 2.22. Le paquet est fourni par la plupart des distributions Linux de pentest comme Black Arch et Kali Linux.

L’outil est fourni avec de nombreuses wordlists, dont big.txt et common.txt (sa wordlist par défaut). Dirb est également fourni avec deux utilitaires : html2dic qui est un équivalent de cewl et gendict qui est un équivalent de crunch, tous deux utilisés pour la génération de wordlists.

Bien que dirb soit l’un des plus anciens outils de découverte web, il propose la plupart des options avancées comme les headers personnalisés, les extensions personnalisées, le proxy authentifié et même la récursion interactive. Malheureusement, l’outil est l’un des rares à ne pas proposer de capacités multithread.

Avantages

  • Spécifier plusieurs wordlists (séparées par des virgules)
  • Mode récursif (par défaut, ou avec l’option -R pour le mode interactif)

Inconvénients

  • Pas d’option multithread
  • Uniquement la méthode GET
  • Pas de filtres évolués
  • Une seule option de sortie

DirBuster

DirBuster est un scanner de contenu web écrit en Java et fourni par l’OWASP Foundation depuis 2007. Le projet n’est plus maintenu par l’OWASP et les fonctionnalités proposées font désormais partie du OWASP ZAP Proxy. La dernière release de l’outil était la version 1.0-RC1 en 2008. DirBuster a la particularité de fournir une GUI :

DirBuster

Même si le projet n’est plus proposé par l’OWASP, le code source de l’outil est disponible sur SourceForge. L’outil est également fourni par la plupart des distributions Linux de pentest.

L’outil est packagé avec 8 wordlists dont directory-list-1.0.txt et apache-user-enum-2.0.txt.

Avantages

  • Scraping de site web (extraction des dossiers depuis les attributs src et href)
  • Prise en charge de l’authentification digest access
  • Spécifier le point de Fuzzing dans l’URL
  • Rapports en XML, CSV ou TXT

Inconvénients

  • Uniquement les méthodes GET/HEAD
  • GUI Java

Dirsearch

Dirsearch est un outil en ligne de commande conçu pour brute forcer les répertoires et fichiers des serveurs web. L’outil est écrit en Python3 depuis 2015 mais a été conçu en 2014 avec Python2. Dirsearch est toujours maintenu et sa dernière release date de décembre 2020.

En tant qu’outil riche en fonctionnalités, dirsearch offre aux utilisateurs la possibilité de réaliser une découverte de contenu web complexe, avec de nombreux vecteurs pour la wordlist, une grande précision, des performances impressionnantes, des paramètres de connexion/requête avancés, des techniques de brute-force modernes et une sortie soignée.

Comme vous pouvez le voir, dirsearch propose de nombreuses options pour transformer la wordlist comme l’exclusion d’extension, le suffixe, la suppression d’extension. Dirsearch propose même la gestion des erreurs 429 - Too Many Requests, la gestion des requêtes raw et des vérifications par regex. Dirsearch est fourni avec une wordlist par défaut nommée dicc.txt qui contient des tags %EXT% qui seront remplacés par les extensions définies par l’utilisateur.

Enfin, dirsearch propose plusieurs formats de rapport dont texte, JSON, XML, Markdown et CSV.

Avantages

  • Prise en charge de plusieurs URLs et du CIDR
  • Vérification de plusieurs extensions
  • Prise en charge de plusieurs wordlists avec manipulation de wordlist
  • Prise en charge des requêtes raw avec l’option --raw, et de n’importe quelle méthode HTTP avec -m.
  • Sortie colorée avec de nombreux formats d’export et des filtres regex

Inconvénients

  • Beaucoup d’options, un scan personnalisé peut être long à configurer
  • Pas de moyen rapide de fuzzer une partie spécifique d’une URL

FFUF

FFUF (Fuzz Faster U Fool) est un web fuzzer écrit en Go. L’outil est assez récent (première release en 2018) et activement mis à jour. Contrairement aux outils précédents, FFUF se veut un outil de fuzzing HTTP qui peut être utilisé non seulement pour la découverte de contenu mais aussi pour le fuzzing de paramètres. Grâce à sa conception, FFUF a également la capacité de fuzzer des headers tels que le VHOST.

Comme Dirsearch, FFUF propose des options de filtre et de « matcher » (dont regex) pour trier les résultats, et de nombreux formats de sortie (dont JSON et XML). FFUF est le seul à proposer un mode de fonctionnement multi-wordlist, comme l’attack type dans BurpSuite intruder. Ce mode peut être utilisé pour une attaque par bruteforce ou une découverte par fuzzing complexe.

Enfin, on peut noter que l’option -D nous permet de réutiliser certaines wordlists de Dirsearch comme dicc.txt.

Avantages

  • Option « Replay-proxy » qui peut être associée à d’autres outils comme BurpSuite
  • Modes de fonctionnement multi-wordlist
  • Sortie colorisée
  • Calibration de filtrage personnalisée / automatique

Inconvénients

  • beaucoup d’options, un scan personnalisé peut être long à configurer

Gobuster

Comme son nom l’indique, Gobuster est un outil écrit en Go. La première release de gobuster date de 2015 et la dernière d’octobre 2020. Gobuster est un outil puissant à usages multiples :

Gobuster est un outil utilisé pour brute-forcer : Les URIs (répertoires et fichiers) des sites web. Les sous-domaines DNS (avec prise en charge des wildcards). Les noms de Virtual Host sur les serveurs web ciblés. Les buckets Amazon S3 ouverts

Comme mentionné dans la description du projet, Gobuster a été créé à l’origine pour éviter la GUI Java de Dirbuster et prend en charge la découverte de contenu avec plusieurs extensions à la fois.

Comme indiqué dans la description de l’outil, Gobuster se veut un outil simple sans options superflues. Notez que Gobuster est fourni sans aucune wordlist.

Avantages

  • Extensions multiples
  • Option -d pour découvrir les fichiers de backup
  • Options DNS, VHOST et S3

Inconvénients

  • Pas de récursion
  • Wordlist unique
  • Pas de matching regex
  • Un seul format de sortie (TXT)

Wfuzz

Wfuzz est un web fuzzer écrit en Python3 et fourni par Xavi Mendez depuis 2014.

Wfuzz a été créé pour faciliter la tâche lors des audits d’applications web et repose sur un concept simple : il remplace toute référence au mot-clé FUZZ par la valeur d’un payload donné.

L’outil est toujours maintenu avec une release récente en novembre 2020. Le paquet est fourni par la plupart des distributions Linux de pentest.

L’outil est fourni avec de nombreuses wordlists : General (big.txt, common.txt, medium.txt…), Webservices (ws-dirs.txt et ws-files.txt), Injections (SQL.txt, XSS.txt, Traversal.txt…), Stress (alphanum_case.txt, char.txt…), Vulns (cgis.txt, coldfusion.txt, iis.txt…) et autres.

Comme Fuff, Wfuzz remplace le mot-clé FUZZ par un payload issu d’une wordlist donnée. Wfuzz propose plusieurs filtres dont des filtres regex (--ss/hs) et prend en charge plusieurs sorties (JSON, CSV, …). De plus, Wfuzz est l’un des rares outils à prendre en charge à la fois l’auth basic, l’auth NTLM et l’auth digest.

Avantages

  • Encoders (urlencode, base64, uri_double_hex…) et scripts
  • Chaînage d’encodages
  • Authentification Basic/NTLM/Digest
  • Sortie colorisée

Inconvénients

  • Wordlist unique

Bonus - BFAC

BFAC (Backup File Artifacts Checker) n’est pas un outil conçu pour rechercher de nouveaux dossiers, fichiers ou routes, mais un outil conçu pour rechercher des fichiers de backup.

BFAC (Backup File Artifacts Checker) est un outil automatisé qui recherche les artefacts de backup susceptibles de divulguer le code source de l’application web. Ces artefacts peuvent également entraîner la fuite d’informations sensibles, comme des mots de passe, la structure des répertoires, etc. L’objectif de BFAC est d’être un outil tout-en-un pour le test en boîte noire des artefacts de fichiers de backup.

À partir d’une liste d’URI de fichiers, BFAC va tenter de récupérer les fichiers de backup associés avec une liste de tests codée en dur. Par exemple, pour le fichier /index.php, BFAC ne va pas seulement tenter de récupérer /index.php.swp et /index.php.tmp, mais inclut aussi des tests comme /Copy_(2)_of_index.php, /index.bak1 ou /index.csproj.

Comme vous pouvez l’imaginer, BFAC doit être utilisé en complément des outils précédents. Il prend en charge la plupart des fonctionnalités attendues comme le support des proxy, les headers personnalisés et différentes sorties.

Avantages

  • Outil complémentaire
  • Efficace avec moins de requêtes qu’un outil de découverte web classique

Inconvénients

  • Même si l’outil est toujours maintenu, le dépôt ne fournit qu’une seule release

Cas d’usage

Découverte simple sur des applications PHP

L’utilisation principale de ces outils est la découverte de fichiers sur un serveur web classique, comme un site PHP tournant sur un apache2. La recherche de fichiers sur ce type de serveur web mène souvent à des erreurs HTTP comme 404 - File not found, 403 - Forbidden ou à des succès HTTP comme 200 - OK. D’autres codes de statut HTTP peuvent être rencontrés, comme 302 - Found, 429 - Too Many Requests, 500 - Internal Server Error

Selon la configuration du serveur, un auditeur peut ou non inclure certains codes de statut HTTP lors de la découverte de fichiers. La configuration par défaut de la plupart des outils consiste à masquer 404 - File not found des résultats. Les codes de statut affichés peuvent varier d’un outil à l’autre mais 200 - OK est le résultat affiché le plus courant.

c.-à-d. que, par défaut, Dirsearch affichera non seulement le code de statut 200 mais aussi 301, 302, etc.

$ dirsearch -u http://localhost/
$ dirsearch -u http://localhost/ -e php
$ dirsearch -u http://localhost/ -e php,php5,sql -w /usr/share/wordlists/raft-large-words.txt -f

Note : par défaut, dirsearch remplace uniquement le mot-clé %EXT% par les extensions. Utiliser le flag -f forcera dirsearch à ajouter les extensions pour une wordlist donnée. Cette option est inutile si votre wordlist contient déjà des extensions de fichiers.

La même tâche peut être réalisée par les autres outils :

$ dirb http://localhost/ /usr/share/wordlists/raft-large-words.txt -X php,php5,sql
$ gobuster dir -u http://localhost/ -w /usr/share/wordlists/raft-large-words.txt -x php,php5,sql
$ ffuf -u http://localhost/FUZZ -w /usr/share/wordlists/raft-large-words.txt -e php,php5,sql
$ wfuzz --hc 404 -w /usr/share/wordlists/raft-large-words.txt -w exts.txt http://localhost/FUZZFUZ2Z

Serveur web avec une page personnalisée pour les erreurs 40X

Parfois, le serveur ne répond pas comme attendu par vos outils et renvoie une erreur 403 au lieu d’une erreur 404, ou pire un code de statut 200 avec une page d’erreur personnalisée.

Dans ce cas, l’auditeur doit configurer son outil pour correspondre à la réponse du serveur. Pour le cas du 403, la première solution consiste à exclure les résultats 403 de son outil :

$ dirb http://localhost/ /usr/share/wordlists/raft-large-words.txt -X php,php5,sql -N 403
$ dirsearch -u http://localhost/ -e php,php5,sql -w /usr/share/wordlists/raft-large-words.txt -f -x 403
$ gobuster dir -u http://localhost/ -w /usr/share/wordlists/raft-large-words.txt -x php,php5,sql -b 403,404
$ ffuf -u http://localhost/FUZZ -w /usr/share/wordlists/raft-large-words.txt -e php,php5,sql -fc 403
$ wfuzz --hc 404,403 -w /usr/share/wordlists/raft-large-words.txt -w exts.txt http://localhost/FUZZFUZ2Z

Avec cette solution, l’auditeur risque de manquer des erreurs 403 intéressantes. La seconde option consiste à filtrer plus précisément le contenu que vous ne recherchez pas.

Si l’erreur 403 est une page personnalisée ou si vous obtenez un code de statut 200 avec un message d’erreur, vous pouvez filtrer les pages web par leur contenu et non par leur code de statut. Les outils proposent plusieurs façons de le faire : vous pouvez soit filtrer par taille de page (en supposant que la page d’erreur fasse toujours la même taille), soit filtrer par mots ou par regex présents dans la page web.

Page d'erreur de https://wordpress.com/

c.-à-d. que, si un site web renvoie un code de statut HTTP 200 avec une page HTML contenant la phrase Page not found, vous pouvez filtrer de la manière suivante :

$ dirsearch -u http://localhost/ --exclude-texts="Page not found" -e php,php5,sql -w /usr/share/wordlists/raft-large-words.txt -f
$ ffuf -u http://localhost/FUZZ -fr "Page not found" -w /usr/share/wordlists/raft-large-words.txt -e php,php5,sql
$ wfuzz --hs "Page not found" --hc 404 -w /usr/share/wordlists/raft-large-words.txt -w exts.txt http://localhost/FUZZFUZ2Z

Notez que cette méthode n’est pas disponible pour tous les outils.

Fuzzing sur une API Rest

Avec l’évolution des standards de développement web, les auditeurs rencontrent des techniques de routage web de plus en plus variées. Il n’est donc pas rare que des ressources soient accessibles via des routes dynamiques. C’est le cas des WEB API RESTfull où certaines ressources doivent être fuzzées au milieu d’une URI.

OVH API - https://api.ovh.com

Prenons l’exemple d’une API REST où la route /vps/{serviceName}/ips est disponible avec des requêtes GET (et où la route /vps/{serviceName} n’existe pas). Pour énumérer ce paramètre, vous avez 3 possibilités :

  • Réutiliser les exemples précédents et définir /ips comme une extension 🧐 ;
  • Utiliser l’option de suffixe des outils si disponible ;
  • Utiliser un outil de fuzzing dédié comme ffuf ou wfuzz pour réaliser un fuzzing de paramètre précis (recommandé).
$ dirsearch -u http://localhost/vps/ --suffixes /ips -w /usr/share/wordlists/raft-large-words.txt
$ ffuf -u http://localhost/vps/FUZZ/ips -w /usr/share/wordlists/raft-large-words.txt
$ wfuzz --hc 404 -w /usr/share/wordlists/raft-large-words.txt http://localhost/vps/FUZZ/ips

IDOR en POST avec ID incrémental

Parfois, l’emplacement des ressources repose sur un paramètre plus complexe comme le header Accept-Language, un paramètre HTTP POST ou même une adresse IP.

Lors d’un pentest, les auditeurs de SEC-IT ont rencontré une vulnérabilité permettant aux utilisateurs de télécharger des PDF sur la page /files/pdf avec le paramètre POST {"objectId": "X"} où X est un entier. La vulnérabilité elle-même était une IDOR (Insecure Direct Object Reference) : un utilisateur pouvait télécharger n’importe quel PDF sans restriction de privilège. Le problème est que, même si le paramètre vulnérable était un ID pseudo-incrémental, il y avait un pas aléatoire entre chaque ID, ce qui rend l’exfiltration plus difficile sans outil.

Pour réaliser ces exfiltrations de PDF, des web fuzzers comme ffuf et wfuzz peuvent être utilisés pour fuzzer le paramètre POST objectId :

$ ffuf -u http://localhost/files/pdf -X POST -d '{"objectId" : "FUZZ"}' -w /usr/share/wordlists/ints.txt
$ wfuzz -z file,/usr/share/wordlists/ints.txt -d '{"objectId" : "FUZZ"}' http://localhost/files/pdf

Tableau comparatif

Sans plus attendre, voici un tableau comparatif des différents outils abordés dans cet article :

(ouvrir en image ici)

DirbDirbusterDirsearchFFUFGoBusterWfuzzRustbusterFinalReconMonsoonBFAC
LangageCJavaPython3GoGoPython3RustPython3GoPython3
Première release27/04/2005200707/07/201408/11/201821/07/201523/10/201420/05/201905/05/201912/11/201708/11/2017
Dernière release19/11/201401/05/201308/12/202024/01/202119/10/202006/11/202024/05/201923/11/202028/10/202008/11/2017
Version actuelle2.221.0-RC10.4.11.2.13.1.03.1.01.1.0aucun versioning0.6.01.0
LicenceGPLv2LGPL-2GPLv2MITApache License 2.0GPLv2GPLv3MITMITGPLv3
MaintenuNonNonOuiOuiOuiOuiOuiOuiOuiOui
GUI/CLICLIGUI (Java)CLI (colorisé par défaut)CLI (option de colorisation)CLICLI (option de colorisation)CLICLI (colorisé par défaut)CLI (colorisé par défaut)CLI (colorisé par défaut)
Fichier d'options de profilNonNon mais possibilité de modifier les threads, WL et extensions par défautOui (default.conf)Oui (-config)NonOui (--recipe)NonNonOui (-f)Non
SortieNon (-o, texte uniquement)Oui (XML, CSV, TXT)Oui (JSON, XML, MD, CSV, TXT)Oui (JSON, EJSON, HTML, MD, CSV, ECSV)Non (-o, texte uniquement)Oui (-o, JSON, CSV, HTML, Raw)Non (-o, texte uniquement)Oui (-o, XML, CSV, TXT)Non (--logfile, texte uniquement)Oui (JSON, CSV, TXT)
MultithreadNonJusqu'à 500Oui (-t)Oui (-t)Oui (-t)Oui (-t)Oui (-t)Oui (-t)Oui (-t)Oui (--threads)
DélaiOui (-z)Oui (Rate limit)Oui (-s)Oui (-p), accepte un intervalleOui (--delay)Oui (-s)NonNonOui (--requests-per-second)Oui (Rate limit)
Timeout personnaliséNonOuiOui (--timeout)Oui (-timeout)Oui (--timeout)Oui (--req-delay)NonOui (-T)NonOui (--timeout)
ProxyOui (-p/-P, socks5)Oui (non spécifié, authentifié)Oui (--proxy, http/socks5)Oui (-x, http, voir issue 50)Oui(--proxy, http(s) )Oui (-p) Socks4 / Socks5 / HTTP (non authentifié)NonNonOui (SOCKS5/HTTP(s) authentifié)Oui (--proxy, http(s)/socks5 authentifié)
AuthBasicBasic / Digest / NTLMBasic avec HeadersBasic avec HeadersBasic (-U/-P)Basic / Digest / NTLMBasic avec HeadersNonBasic (-u)Basic avec Headers
WL par défautcommon.txt (4614)Nondicc.txt (9000)NonNonNonNondirb_common.txt (4614)NonN/A
WL fourniesOui (plus de 30)Oui (8)Oui (5)NonNonOui (plus de 30)NonOui (3)NonN/A
RécursionPar défaut, option disponibleOuiOui (-r)Oui (-recursion)NonOui (-R)NonNonNonN/A
Profondeur de récursionNon mais mode interactif disponibleNonOui (-R) + interactifOui (-recursion-depth)N/AOui (-R)N/AN/AN/AN/A
URLs multiplesNonNonOui (-l) / CIDROui (via une wordlist d'hôtes)NonOui (via une wordlist d'hôtes)NonNonNonOui (-L)
WL multiplesOui (séparées par des virgules)NonOui, séparées par des virgulesOui (répéter -w)NonOui (répéter -w)Oui (pour plusieurs points de Fuzzing)NonNonN/A
Manipulation de WLNonNonOui (nombreuses transformations)NonNonOui (via encoders et script)NonNonNonN/A
EncodersNonNonNonNonNonOuiNonNonNonN/A
Extension uniqueOui (-X/-x)OuiOui (-e)Oui (-e)Oui (-x)OuiOui (-e)Oui (-e)OuiN/A
Extensions multiplesOui (-X/-x)Oui (séparées par des virgules)Oui (-e, séparées par des virgules)Oui (-e, séparées par des virgules)Oui (-x, séparées par des virgules)Oui (avec une wordlist donnée)Oui (-e, séparées par des virgules)Oui (-e, séparées par des virgules)NonN/A
User-Agent personnaliséOui (-a/-H)OuiOui (--user-agent) + aléatoireOui (via header -H)Oui (-a) + aléatoireOui (via header -H)Oui (-a)NonOui (via header -H)Oui (-ua)
Cookie personnaliséOui (-c/-H)Oui (via headers)Oui (--cookie)Oui (via header -H)Oui (-c)Oui (-b)Oui (via header -H)NonOui (via header -H)Oui (--cookie)
Header personnaliséOui (-H)OuiOui (-H) + fichier HeadersOui (-H)Oui (-H)Oui (-H)Oui (-H)NonOui (-H)Oui (--headers)
Méthode personnaliséeNonNonOui (-m)Oui (-x)Oui (-m)Oui (-X)Oui (-X)NonOui (-X)Non
Fuzzing d'URL (à n'importe quel endroit)NonOuiPas nativement mais contournable avec --suffixesOuiNonOuiOui (mode fuzz)NonOui (mode fuzz)N/A
Fuzzing des données POSTNonNonNonOui (-d)NonOui (-d)Oui (mode fuzz)NonOui (mode fuzz)N/A
Fuzzing de headerNonNonNonOui (-H)NonOuiOui (mode fuzz)NonOui (mode fuzz)N/A
Fuzzing de méthodeNonNonNonOui (-X FUZZ)NonOui (-X FUZZ)Oui (mode fuzz)NonOui (mode fuzz)N/A
Ingestion de fichier rawNonNonOui (--raw)Oui (-request)NonNonNonNonOui (--template-file)Non
Suivre les redirections (302)Oui + option (-N)Oui + optionOui (-F)Oui (-r)Oui (-r)Oui (-L)NonNonOui (--follow-redirect)Non
Filtres personnalisésNonNonOui (--excludes-*, basé sur le texte, la taille, une regex)Oui (-m*, -f*, basé sur le code, la taille, une regex)Limité (code de statut, -s/-b)Oui (basé sur le code, les mots, une regex)Oui (basé sur le code, une chaîne)NonOui (taille, code, regex)Oui (code, taille ou les deux)
Option fichiers de backupNonNonNonNonOui (-d)NonNonNonNonOui
Replay proxyNonNonOui (--replay-proxy)Oui (-replay-proxy)NonNonNonNonNonNon
Ignorer les erreurs de certificatPar défaut ?Par défaut ?Par défautPar défaut, (option -k)Oui (-k)Par défautOui (-k)Oui (-s)Oui (-k)Par défaut
Spécifier l'IP de connexionNonNonOui (--ip)NonNonOui (--ip)NonNonNonNon
Énumération de VhostNonNonNonOuiOuiOuiOuiNonOuiN/A
Énumération de sous-domainesNonNonNonOuiOuiOuiOuiOuiOuiN/A
Énumération S3NonNonNonNonOuiNonNonNonNonN/A

À propos

L’article original a été publié sur le blog de mon entreprise https://blog.sec-it.fr/.

Vous pouvez trouver SEC-IT à l’adresse https://www.sec-it.fr.

Une partie de ce contenu est sous licence MIT / © 2021 SEC-IT.