15/11/2024

Détection des versions de services et systèmes d’exploitation avec Nmap

I. Présentation

Dans ce chapitre, nous allons apprendre à utiliser Nmap pour découvrir et détecter précisément les versions des services et systèmes d’exploitation utilisés par les hôtes scannés. Nous verrons en détail le fonctionnement de Nmap pour accomplir cette tâche, ainsi que les limites de l’outil pour mieux comprendre et interpréter ses résultats.

Nous l’avons vu dans les précédents chapitres de ce cours, par défaut, Nmap ne va pas chercher à savoir quel service est exposé sur les ports qu’il scanne et considère comme ouvert. Ainsi, vous pourriez mettre en écoute un service web sur le port TCP/22, Nmap continuera à le rapporter comme ouvert, certes, mais en tant que service “SSH”. Cela parce qu’il utilise une base de données locale à votre système pour rechercher une relation entre un port/protocole et le nom d’un service (le fichier “/etc/services/”).

Dans la majorité des cas, Nmap vous fournira une information correcte, car il est rare dans un environnement de production de trouver de tels cas. Cependant, les cas de figure restants seront des situations où un service classique (SSH, HTTP, etc.) sera exposé sur un port non classique (par exemple 2022 pour un service SSH), Nmap ne trouvera alors pas de correspondance dans sa base locale, ou une qui ne correspond pas à la réalité, et vous passerez à côté d’une information importante.

Heureusement, Nmap propose des options et mécanismes très précis pour découvrir quel service exact peut se cacher derrière un port ouvert. Il possède même une base de données de requêtes et signatures permettant d’identifier les technologies et versions exactes. En plus des services, Nmap peut de la même manière identifier la technologie utilisée et sa version.

C’est ce que nous allons voir dans ce chapitre.

II. Comment détecter une technologie ou une version

A. Rappel sur l’identification d’une technologie ou version

L’identification d’une technologie et d’une version consiste à récupérer le nom du service, du CMS, de l’application ou du logiciel qui est en écoute sur le port ciblé. Par exemple, une page web est gérée par un CMS (WordPress), exécuté par un service web (Apache, IIS, Nginx) et hébergé par un serveur (Linux ou Windows). Mais comment savoir quel service web est en place ?

La méthodologie classique pour connaître cette information est le banner grabbing (récupération de bannière) qui consiste simplement à repérer où le service en question affiche cette information et à lire la donnée. Bien souvent, dans leur configuration ou traitement par défaut, les services affichent leur nom et même leur version en première réponse après une connexion.

Affichage d’une version dès l’établissement d’une connexion TCP par un service FTP.
Affichage d’une version dès l’établissement d’une connexion TCP par un service FTP.

Nous voyons ici qu’une simple connexion TCP à ce service via “telnet” entraîne en réponse un paquet TCP contenant sa technologie et sa version.

Lorsque l’on a une petite idée du type de service qui est en face de nous, il est également possible d’envoyer des commandes ou requêtes spécifiques à ce service pour en extraire des informations. Ces requêtes/commandes peuvent aussi être envoyées “à l’aveugle” (sans être sûr qu’il s’agit du bon type de service), en espérant que l’une d’entre elles provoque une réponse du service en question.

Dans d’autres cas un peu plus avancés, il est nécessaire d’envoyer des paquets spécifiques pour causer une réaction, comme une erreur, qui fournira des informations détaillées sur la version ou la technologie utilisée.

Vous vous en doutez à présent, Nmap va utiliser toutes ces techniques pour tenter d’identifier précisément le type de service hébergé sur un port, ainsi que le nom de sa technologie et sa version.

B. Comprendre les Probes et Match de Nmap

Pour effectuer toutes ces vérifications sur chaque port scanné, Nmap utilise une base de données locale qui est fréquemment mise à jour (au même titre que le binaire ou ses modules). Il s’agit d’un fichier texte de plusieurs milliers de lignes : “/usr/share/nmap/nmap-service-probes”.

Ce fichier est composé de nombreuses entrées, toutes sont organisées autour de deux directives principales :

  • Les “Probe” : il s’agit de la définition du paquet qu’enverra Nmap pour tenter de provoquer une réaction du service à identifier. Voyez cela comme des tentatives à l’aveugle du type “Bonjour ? Guten Tag ? Hello ? Hum… Buenos Dias peut-être ?”. Dès que le service ciblé recevra un probe qu’il comprend (c’est-à-dire parlant le bon protocole), il répondra à Nmap, qui aura alors une confirmation du type de service dont il s’agit.
  • Les “Match” : ce sont des expressions régulières qu’appliquera Nmap sur la réponse obtenue. Si l’envoi d’une requête HTTP GET a provoqué une réponse du service, il appliquera sur cette réponse des dizaines d’expressions régulières afin d’identifier la présence, par exemple, du mot “Apache”, “Nginx”, “Microsoft IIS”, etc.

Il existe quelques autres directives pour des cas spécifiques, mais les principales pour comprendre le fonctionnement de Nmap et personnaliser son utilisation sont celles-ci. Pour que cette partie théorie soit plus concrète, voici un exemple :

Exemple de Probe présent dans le fichier “/usr/share/nmap/nmap-service-probes” de Nmap.
Exemple de Probe présent dans le fichier “/usr/share/nmap/nmap-service-probes” de Nmap.

Nous voyons en première ligne de cet exemple un Probe assez simple à comprendre et nommé “GetRequest”. Il s’agit d’un paquet TCP contenant une requête HTTP GET vide sur la racine du service web en utilisant HTTP/1.0, puis un saut de ligne et une ligne vide.

La ligne “ports” indique à Nmap pour quel port il faut envoyer ce Probe. Cela permet de prioriser les tests et de gagner un certain temps.

Enfin, nous avons deux exemples de “match”. Le premier par exemple catégorisera le service web scanné en “ajp13” si l’expression régulière contenue dans cette ligne match avec la réponse du service reçue.

Pour comprendre à quoi peuvent ressembler les Probes, voici une liste de quelques Probes que vous pourrez trouver dans ce fichier (il y en a 188 en tout en date d’écriture de ce cours).

Exemple de plusieurs Probes utilisés par Nmap et présents dans le fichier “/usr/share/nmap/nmap-service-probes”.
Exemple de plusieurs Probes utilisés par Nmap et présents dans le fichier “/usr/share/nmap/nmap-service-probes”.

Il faut ici notamment s’intéresser aux deux premiers (nomma “NULL” et “GenericLines”), qui consistent juste à envoyer un paquet TCP vide ou contenant un renvoi à la ligne. Bien souvent, les services présents sur les serveurs s’annoncent avec précision dès qu’une connexion est reçue, sans action, commande ou requête spécifique du client.

Voici le cas d'un match un peu plus complexe :

# Match Nginx + version dans une page d'erreur 400
match ssl/http m|^HTTP/1.1 400 Bad Request\r\n.*?Server: nginx/([\d.]+)[^\r\n]*?\r\n.*<title>400 The plain HTTP request was sent to HTTPS port</title>|s p/nginx/ v/$1/ cpe:/a:igor_sysoev:nginx:$1/

L'expression régulière exacte est ici contenue entre le "m|" et le "|", qui délimite toute expression régulière dans ce fichier. Prenez ici le temps de bien lire l'entièreté de cet exemple. Vous remarquerez la présence d'une sélection dans l’expression régulière : “([\d.]+)”, celle-ci permet d'isoler une version. Également, cet exemple défini d'autres éléments comme le nom du produit "p/nginx/", la version récupérée "v/$1/" et le CPE avec version "cpe:/a:igor_sysoev:nginx:$1/".

Un CPE (Common Platform Enumeration) est un système de notation standardisé utilisé pour identifier et décrire les logiciels et matériels. Ce format permet une gestion plus efficace des vulnérabilités et des configurations de sécurité, et surtout une manière unifiée de les représenter, quel que soit le produit en question. Voici deux exemples de CPE : “cpe:/o:microsoft:windows_8.1:r1” et "cpe:/a:apache:http_server:2.4.35

On identifie ici clairement leurs types “o” pour OS, “a” pour application, vendeur, produit, et versions.

Ainsi en cas de match avec l'une de cette expression régulière, nous récupérerons non seulement le nom du service, mais aussi sa version et le CPE exact, ce qui nous facilitera notamment la recherche de CVE impactant cette version. Vous retrouverez notamment ces informations dans la sortie standard de Nmap et verrez qu'elles seront très utiles pour d'autres usages que nous évoquerons dans quelques chapitres.

La syntaxe exacte des matchs et plus globalement des directives du fichier “/usr/share/nmap/nmap-service-probes” ne s’arrête pas là et peut paraître assez complexe lorsque l’on n’est pas habitué à manipuler Nmap et ses résultats. Cependant, il faut au moins garder en tête son existence et son fonctionnement général, cela sera utile plus tard lorsque vous souhaiterez comprendre ou débugger un résultat, personnaliser un scan ou même contribuer au développement de Nmap.

III. Utiliser Nmap pour détecter des versions

À présent, nous allons utiliser toute cette mécanique complexe de Probe et Match via une option simple : “-sV”. Celle-ci permet simplement d’indiquer à Nmap : tente de découvrir précisément les services et versions des ports que tu détermines comme ouvert.

# Activer la détection des services et versions
nmap 192.168.1.0/24 -sV

Voici un exemple complet du résultat d’une telle commande :

Résultat de la détection de versions des applications exposées sur le réseau par Nmap.
Résultat de la détection de versions des applications exposées sur le réseau par Nmap.

Nous voyons ici que Nmap est parvenu à identifier toutes les versions des services réseau exposés par cette cible et qu’il nous affiche ces informations dans une nouvelle colonne “VERSION”. Il est possible de voir des informations assez précises, allant parfois jusqu’au système d’exploitation, si cette information fait partie de la signature récupérée.

Pour comprendre en détail ce qu’il se passe pendant un scan de vulnérabilité, nous pouvons utiliser l’option “--version-trace”. Elle permettra d’avoir une vue en mode “debug” et affichera notamment le Probe qui a permis la détection :

# Activer le debug de la détection de version
nmap 192.168.1.0/24 -sV --version-trace

En résultat, nous aurons de nombreuses informations et il va falloir trier un peu. Tentez d’identifier les lignes qui commencent par “Service scan hard match”. Vous verrez alors des lignes telles que celles-ci :

Service scan hard match (Probe NULL matched with NULL line 789): 10.10.10.187:21 is ftp. Version: |vsftpd|3.0.3||
Service scan hard match (Probe NULL matched with NULL line 3525): 10.10.10.187:22 is ssh. Version: |OpenSSH|7.4p1 Debian 10+deb9u7|protocol 2.0|
Service scan hard match (Probe GetRequest matched with GetRequest line 10510): 10.10.10.187:80 is http. Version: |Apache httpd|2.4.25|(Debian)|

Nous voyons très clairement quels Probes ont permis la détection de technologie et version (ici les Probes NULL” et “GetRequest”), ainsi que les informations récupérées.

IV. Maitriser les tests et la précision des détections

Nous allons à présent revenir sur une directive du fichier “/usr/share/nmap/nmap-service-probes” sur laquelle nous ne nous sommes pas attardés tout à l’heure :

Directive “rarity” des Probes dans le fichier “/usr/share/nmap/nmap-service-probes”.
Directive “rarity” des Probes dans le fichier “/usr/share/nmap/nmap-service-probes”.

Cette directive permet d’indiquer la rareté (comprendre : priorité/probabilité) associée à un Probe. Cette notation de 1 à 9 permet d’avoir la main sur le niveau d’exhaustivité de l’analyse faite par Nmap lors de l’envoi des Probes. Dans le système de “notation” mis en place par Nmap, une rareté à 1 permet d’avoir en retour une information dans la grande majorité des cas, alors qu’une rareté à 8 ou 9 représente plus un cas très particulier propre à une configuration ou un service rarement présent.

Pour être plus clair, dans un cas par défaut, Nmap va envoyer sur chaque service à identifier les Probes qui ont une rareté de 1 à 7. Pour que vous vous représentiez mieux la répartition des Probes par rarity, voici leur décompte :

$ grep -E "^rarity" nmap-service-probes |sort |uniq -c

6 rarity 1
1 rarity 2
3 rarity 3
8 rarity 4
9 rarity 5
13 rarity 6
8 rarity 7
81 rarity 8
54 rarity 9

Cela peut paraître contre-intuitif, il y a plus de “rarity” 8 et 9 que le reste. C’est justement parce que les Probe a rareté 1 sont génériques et fonctionnent dans la majorité des cas, peu importe le service (rappelez-vous du Probe “NULL” qui envoie simplement un paquet TCP vide). Alors que les Probes plus complexes sont presque uniques par service.

Si l’on souhaite gérer manuellement les Probes que l’on souhaite utiliser dans notre scan de version, nous pouvons utiliser l’option “--version-intensity”. Voici deux exemples :

# Détection de version moins précise que par défaut
nmap 192.168.1.0/24 -sV --version-intensity 2

# Détection très poussée, utilisant tous les Probes existants
nmap 192.168.1.0/24 -sV --version-intensity 9

Pour finir sur ce sujet, voici un exemple de Probe 9 et 8:

Exemples de Probe à rarity 8 et 9 dans le fichier “/usr/share/nmap/nmap-service-probes”.
Exemples de Probe à rarity 8 et 9 dans le fichier “/usr/share/nmap/nmap-service-probes”.

Ces deux Probes permettent de détecter des serveurs Quake1 et Quake2 (le jeu vidéo). Intéressant pour le côté nostalgique, mais peu probable que ça nous serve au quotidien.

En fonction de vos besoins de précision ou de rapidité, rappelez-vous donc que ce principe de “rarity” existe et peut jouer sur le résultat.

V. Utiliser Nmap pour détecter des systèmes d'exploitation

Nous allons maintenant voir comment Nmap peut nous aider à détecter les systèmes d’exploitation des hôtes scannés et détectés sur un réseau. Il faut pour cela utiliser l’option “-O” (pour “OS Scan”) de Nmap.

# Activation du Scan des OS
nmap -O 10.10.10.0/24

Voici un exemple de résultat, ici Nmap nous indique qu’il s’agit probablement d’un OS Linux, il nous propose différentes statistiques concernant sa version exacte.

Détection de la probabilité d’identification d’un système d’exploitation par Nmap.
Détection de la probabilité d’identification d’un système d’exploitation par Nmap.

Pour établir ce résultat, Nmap va utiliser une multitude de techniques qui fonctionnent de manière très similaire aux Probes et Matches pour la détection de technologies et versions. La différence principale étant que Nmap utilisera des paramètres assez “bas niveau” des protocoles ICMP, TCP, UDP, etc. Voici deux exemples de test pour la détection d’un système d’exploitation Microsoft Windows 11 :

Exemple de test réalisé par Nmap pour la détection d’un OS Windows 11.
Exemples de tests réalisés par Nmap pour la détection d’un OS Windows 11.

Nous n’allons pas nous mentir, il est très difficile d’interpréter ces tests et nous n’allons pas chercher à les comprendre en profondeur dans le cadre d’un cours d’introduction à Nmap. Si vous souhaitez creuser le sujet, sachez que le fichier contenant ces informations est “/usr/share/nmap/nmap-os-db”.

Il faut cependant être conscient que la détection d’un OS est plus une probabilité établie par Nmap qu’une certitude.

VI. Conclusion

Dans ce chapitre, nous avons appris à utiliser les options de Nmap permettant de détecter les technologies, versions et systèmes d’exploitation des services et hôtes scannés. Nous avons maintenant une bonne compréhension de la manière dont procède Nmap pour obtenir ces informations à distance. Nous avons également passé en revue les options pour gérer la verbosité et la précision des tests, ainsi que les limites de l’outil sur ces sujets.

Dans le prochain module, nous allons apprendre à utiliser les scripts NSE de Nmap afin d’effectuer une analyse de sécurité de notre système d’information. Prenez le temps de relire les derniers chapitres si nécessaire, et n’hésitez pas à pratiquer et fouillez vous-même dans les entrailles de l’outil pour mieux maîtriser ce que nous avons appris jusqu’ici.

author avatar
Mickael Dorigny Co-founder
Co-fondateur d'IT-Connect.fr. Auditeur/Pentester chez Orange Cyberdéfense.
Partagez cet article Partager sur Twitter Partager sur Facebook Partager sur Linkedin Envoyer par mail

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.