==Phrack Inc.== Volume 0x0b, Issue 0x39, Phile #0x07 of 0x12 |=---=[ ICMP based remote OS TCP/IP stack fingerprinting techniques ]=---=| |=-----------------------------------------------------------------------=| |=---------------=[ Ofir Arkin & Fyodor Yarochkin ]=---------------------=| traduit de l'anglais par dzeta (dzeta@netcourrier.com) --[ICMP based fingerprinting approach]-- La prise d'empreinte d'OS basé sur TCP se fait un peu vieille et bien- connu aujourd'hui, ici nous voudrions introduire une méthode alternative pour determiner un OS a distance, basé sur des requetes ICMP recue depuis l'hote distant. Certains niveaux d'exactitude ont été réalisées avec différentes plateformes, ce qui, avec quelques systèmes ou classe de plateforme (i.g. *Win) est significativement plus précis que ceux démontré par la méthode de prise d'empreinte basé sur TCP. Comme il est dit plus haut sur la méthode basée sur TCP, la prise d'empreinte ICMP utilise plusieurs tests pour réussir un sondage de la pile TCP/IP de l'OS, mais contrairement à la prise d'empreinte TCP, le nombre de tests demandés pour identifier un OS peut varier de 1 à 4 (en date actuelle de développement). La méthode de prise d'empreinte ICMP sur la découverte de certaines différences dans les réponses ICMP des divers systèmes d'exploitation (principalement due a une incorrecte, voire inconsistante implémentation), a été trouvé par Ofir Arkin durant son "ICMP usage in scanning" projet de recherche. Plus tard, ces découvertes ont été récapitulées dans un arbre logique de décisions que Ofir titre "X project" et pratiquement implémenté dans l'outil Xprobe. --[Information/Noise ratio with ICMP fingerprints]-- Comme cela à été précisé, le nombre de datagrammes que nous avons besoin d'envoyer dans le but de prendre à distance l'empreinte de la machine cible avec des sondages basés ICMP est faible. Très faible. En fait, on peut envoyer un seul datagramme et ne recevoir qu'une seule réponse et ceci nous aidera à identifier plus de 8 différents systèmes d'exploitation (ou classes de systèmes d'exploitation). Le nombre maximal de datagrammes que notre outil va utiliser au developpement actuel est de 4. C'est le même nombre de réponses que nous aurons à analyser. Ceci fait de la prise d'empreinte ICMP un moyen rapide et efficace. Les sondages basés ICMP peuvent être utilisé comme très furtif. Aucun datagrammes malformé/cassé/corrompu ne sont utilisés pour identifier un type d'OS à distance, contrairement aux méthodes communes de prise d'empreinte. L'analyse actuelle du noyau vise la validation des réponses ICMP recues sur des paquets valides, plutot que d'utiliser des paquets eux- même invalide. Les segments de tels paquets apparaissent dans un reseau moyen sur la quotidiennement, et très peu d'IDS sont configurés pour detecter un tel trafic (et ceux qui le sont, sont probablement très bruyant et mal configuré. --[Why it still works?]-- Le désordre hérité parmi les différentes implémentations de piles TCP/IP avec la manipulation des implémentations ICMP qui implémente different standards RFC ( RFC originale 792, le complément RFC 1122, etc), partielle ou incomplet support ICMP (les requetes ICMP variable ne sont pas supportés partout), faible signification des données des messages d'erreur ICMP (qui vérifient tout les champs du datagramme original ?!), erreurs et incompréhension dans les implementations du protocole ICMP, font que notre méthode est viable. --[What do we fingerprint:]-- Plusieurs différences spécifiques aux OS sont utilisés dans la prise d'empreinte ICMP pour identifier le type de syteme d'exploitation à distance : Champs IP d'un datagramme "fautif" à examiner: * Taille totale du champ IP Quelques OS (i.g. *BSD) vont ajouter 20 bytes (sizeof(ipheader)) à la taille totale du champ IP original (qui est provoqué, à cause des erreurs de traitement interne du datagramme, veuillez notez que quand le même paquet de SOCK_RAW est lu le même comportement est observé: La taille du champ du paquet IP en retour sera majoré de 20 bytes). D'autres systèmes d'exploitation vont enlever 20 bytes a la taille totale du champ du paquet IP original du paquet fautif. Un troisieme groupes de systèmes reagiront a ce champ correctement. *IP ID Quelques systèmes ne repetent pas correctement ce champ. (l'ordre du bit du champ à changé) * 3 bits flags et offset Quelques systèmes ne repetent pas correctement ce champ. (l'ordre du bit du champ à changé) * IP header checksum Quelques systèmes d'exploitation vont mal calculer ce champ, d'autres vont carrement le mettre a 0. Un troisieme groupes de systèmes vont répeter ce champ correctement. * UDP header checksum (dans le cas d'un datagramme UDP) La même chose peut arriver avec l'UDP checksum header. En-tête IP des paquets ICMP répondus: *bits priorité chaque datagramme IP a un champ de 8 bits appellés le "TOS byte", qui represente le support IP pour la priorité et la manipulation du Type-Of- Service. Le "TOS byte" est composé de 3 champs. Le "precedence field"\cite{rfc791}, long de 3 bits, est destiné à donner la priorité au datagrammes IP. Il à 8 niveaux de priorité. Le traffic prioritaire plus elevé devrait être envoyé avant le traffic à faible priorité. Le deuxieme champ, long de 4 bits, est le champ "Type-Of-Service". Il est désigné pour décrire de quelle manière le réseau devrait faire des différences entre le débit, le retard, la fiabilité et le coût dans le routage d'un datagramme IP. Le dernier champ, the "MBZ" (must be zero), est inutilisé et doit être à zéro. Les routeurs et serveurs ignorent ce dernier champ. Ce champ est long de 1 bit. Le TOS bytes et champ MBZ sont remplacés par le mécanisme de Diffserv pour QoS. Le RFC 1812 nécessite les points suivants pour les routeurs IPv4 : "4.3.2.5 TOS et priorité Les messages d'erreur ICMP source quench, si envoyés a tous doivent avoir leurs champs de priorité IP à la même valeur que le champ de priorité IP dans le paquet qui a provoqué l'envoi des ICMP source quench. Tout autre message d'erreur ICMP (Destination Unreachable,Redirect, Time Exceeded, and Parameter Problem) devrait avoir la valeur de leur priorité à 6 (INTERNETWORK CONTROL) ou 7 (NETWORK CONTROL). La valeur de priorité IP pour ces messages d'erreurs PEUVENT être configurées". Linux Kernel 2.0.x, 2.2.x, 2.4.x, vont agir comme routeur et vont fixés la valeur de leurs champs de bits priorité à 0xc0 avec les messages d'erreurs ICMP. Les dispositifs de gestion de réseaux vont agir de la même facon que les routeurs CISCO basés sur IOS 11.x-12.x et Foundry Networks switches. * DF bits echoing Quelques piles TCP/IP vont répeter le DF bit avec des datagrammes d'erreurs ICMP, d'autres (comme Linux) vont copier l'octet entierement, en mettant a zéro certains bits, d'autres encore vont ignorer ce champ et configurer leur propre champ. * IP ID filend (linux 2.4.0 - 2.4.4 kernels) Les machines Linux basées sur un kernel 2.4.0-2.4.4 vont fixés la valeur du champ IP identification avec leurs demandes de requetes ICMP et répondent aux messages avec une valeur de 0. Ceci fut fixé plus tard avec les kernels 2.4.5 et supérieurs. * champ IP ttl (ttl la distance de la cible doit être précalculée pour garantir la précision). La valeur du champ est réduite à chaque point que l'en-tête IP est traitée. La RFC791 déclare que la réduction de ce champ reflète le temps passé à traiter le datagramme. La valeur du champ est mesurée par des unités de secondes. La RFC déclare également que la valeur ttl maximum qui peut être fixée est de 255 secondes, ce qui équivaut à 4.25 minutes. Le datagramme doit être jeté si la valeur de ce champ est à zéro avant d'atteindre sa destination. Se réferer à ce champ comme une mesure d'évaluer le temps est un peu trompeur. Des routeurs vont traités le datagramme plus vite qu'en une seconde, et d'autres vont le traiter pendant plus d'une seconde. L'intention réelle est d'avoir une limitation supérieure à la durée de vie du datagramme, ainsi les boucles infinies des datagrammes non délivrées ne bloqueraient pas internet. Avoir une limite à la durée de vie du datagramme nous aide à empecher des vieux doubles d'arriver après qu'un certain temps soit déjà écoulé. Ainsi, quand on retransmet une pièce de l'information qui n'a pas été délivré precedemment, nous pouvons être assuré que le plus vieux double est déjà jeté et qu'il n'interferera pas avec le processus. La valeur du champ IP TTL avec ICMP a deux valeurs séparées, une pour les demandes de messages ICMP l'autre pour les réponses aux demandes. La valeur du champ IP TTL nous aide à identifier certains système d'exploitation et groupes de systèmes d'exploitation. Il nous fournit également les moyens les plus simples d'ajouter un autre contrôle de critère quand nous faisons une demande a d'autres hôtes ou quand on écoute le traffic (sniffing). La prise d'empreinte basée sur le TTL demande une distance TTL de fait pour être précalculées à l'avance (à moins que la prise d'empreinte du systeme basé sur le réseau local soit un système performant). Le message d'erreur ICMP va utiliser les valeurs utilisées elle-mêmes par la réponse aux demandes de messages ICMP. De bonne statistiques sur la dépendance des TTL sur le type d'OS à été rassemblés à : http://www.switch.ch/docs/ttl_default.html (papier de recherche sur les valeurs ttl par défaut) * champ TOS La RFC 1349 définit l'usage du champ Type-of-Service avec les messages ICMP. Il distingue entre les messages d'erreur ICMP (Destination Unreachable, Source Quench, Redirect, Time Exceeded, and Parameter Problem), demandes de messages ICMP (Echo, Router solicitation, Timestamp, Information request, Address Mask request) et les messages de réponses ICMP (Echo reply, Router Advertisement, Timestamp reply, Information reply, Address Mask reply). Des règles simples sont définies: * Un message d'erreur ICMP est toujours envoyé avec le TOS par défault (0x0000) * Un message de réponse ICMP peut être envoyé avec n'importe quelle valeur dans le champ TOS. "Un mécanisme pour permettre aux utilisateurs de spécifier la valeur TOS qui doit être utilisée serait un avantage utile dans pas mal d'applications qui génère des messages de requetes ICMP. Les RFC spécifient de plus que bien que les messages de requêtes ICMP soit normallement envoyé avec le TOS par défaut, il y a parfois de bonnes raisons pour lesquelles ils seraient envoyés avec d'autres valeurs TOS. * Un message de réponse ICMP est envoyé avec la même valeur dans le champ TOS comme c'était utilisé dans les requetes de messages ICMP correspondant. Quelques systèmes d'exploitation vont ignorer la RFC 1349 quand ils envoient des messages de réponse ICMP echo, et n'enverrons pas la même valeur dans le champ TOS comme utilisé dans les messages de requète ICMP correspondant. en-tête ICMP des paquets ICMP répondus: * ICMP error message quoting size Tous les messages d'erreur se composent d'un entête IP, d'un entête ICMP et d'une certaine quantité de données du datagramme original, qui à déclenché l'erreur (aka datagramme fautif). Selon la RFC 792, seulement 64 bits (8 octets) du datagramme original est supposé être inclus dans le message d'erreur ICMP. Toutefois, la RFC 1122 (parue plus tard) recommande plus de 576 octets pour être cités. La plupart des "plus vieilles" implementations de piles TCP inclueront 8 octets dans le message d'erreur ICMP. Linux/HPUX 11.x, Solaris, MacOS et d'autres en inclueront plus. Remarquablement intéressant est le fait que les ingénieurs Solaris n'ont probablement pas lu la RFC assidument ( puisqu'au lieu de 64 bits, Solaris 2.x inclus 64 octets (512 bits) du datagramme original. * intégrité des ICMP error message echoing Un autre objet qui a été remarqué est que quelques implémentations de piles, quand elles renvoient une message d'erreur ICMP, peuvent modifier l'entête IP du paquet fautif et les données fondamentales du protocole, qui est répeté en retour avec le message d'erreur ICMP. Depuis des erreurs, faites pas les programmeurs de piles TCP/IP sont différentes et spécifique à un système d'exploitation, et l'analyse de ces erreurs peuvent donner à un attaquant potentiel la possibilité de faire des prévisions sur le système d'exploitation de la cible. Additional tweaks and twists: * Utilisation différentes des champs de code zéro dans les requetes ICMP écho. Quand un code ICMP dont la valeur du champ est différente de zéro (0) est envoyé avec un message ICMP echo request (type 8), les systèmes d'exploitation qui vont répondre a notre demande avec un message de réponse ICMP echo, sont ceux qui sont basé sur un des systèmes d'exploitation Micro$oft, qui renverront un code ICMP dont la valeur du champ == 0 avec réponse ICMP echo reply. D'autres systèmes d'exploitation ( et dispositif réseaux) répeteront la valeur du champ du code ICMP que nous utilisions avec l'ICMP echo request. Les systèmes d'exploitation Micro$oft agissent contrairement aux directives de la RFC 792 qui instruit les systèmes d'exploitations a ne changer que le type ICMP en Echo reply (type 0), recalculer les checksums et envoyer l'ICMP echo reply. * Utilisation du DF bit echoing avec les messages ICMP query Comme dans le cas des messages d'erreur ICMP, des piles TCP vont répondre à ces demandes, alors que d'autres non. * D'autres messages ICMP: *ICMP timestamp request *ICMP information request *ICMP address mask request Quelques piles TCP/IP supporte ces messages et répondent a quelques unes de ces requêtes. --[Xprobe implementation]-- Actuellement, Xprobe déploie un arbre logique, développé par Ofir Arkin dans "Project X". Initialement, un datagramme UDP est envoyé à un port fermé dans le but de déclencher le message d'erreur ICMP: ICMP unreachable port unreach. (ceci installe une limitation d'avoir au moins un port non filtré sur le système cible sans qu'un service soit en train de tourner). D'ailleurs, quelques tests (icmp unreach content, DF bits, TOS ...), peuvent être combiné dans une requête simple, puisque ils n'affectent pas leurs resultats les uns les autres. Sur la réception du datagramme ICMP unreachable, le contenu du datagramme est examiné et une décision de diagnostic est faite: si d'autres essais en plus sont demandés, selon l'arbre logique, d'autres requetes sont envoyées. --[ Logic tree]--- Récapitulation rapide de l'organisation de l'arbre logique: Initialement toutes les implémentations de piles TCP/IP sont séparées en 2 groupes, ceux qui vont répeter la priorité des bits précedents, et ceux qui ne le feront pas. Ceux qui repetent la priorité des bits (linux 2.0.x, 2.2.x, 2.4.x, Cisco IOS 11.x-12.x, Extreme network switches,etc..), étant différencié encore basé sur la taille de l'ICMP error. (Linux colle avec la RFC 1122 ici et répete jusqu'a 576 octets, alors que les autres dans ce sous-groupe echo seulement 64 bits (8 octets). D'autres contrôles d'intégrité echo sont utilisés pour différencier des routeurs Cisco, des commutateurs extrêmes d'autres réseaux. Time-to-live et champs IP ID de l'ICMP echo reply sont utilisés pour reconnaitre la version du kernel linux. La même approche étant utilisé pour reconnaitre d'autres piles TCP/IP. Les données faisant l'écho de validation (quantité d'octets du datagramme original répétés, validation du checksum, etc ...). Si des informations supplémentaires sont demandés pour diferrencier deux piles IP "similaires", des requetes supplémentaires sont envoyées. (referrez-vous au diagramme a http://www.sys-security.com/html/projects/X.html pour plus de détails sur une explication/graphic de la représentation de l'arbre logique. Un des sérieux problèmes avec l'arbre logique, est que ajouter un nouveau type de système d'exploitation a celui-ci devient extremement douloureux. Parfois, une partie entiere de l'arbre logique doit retravaillée pour s'adapter à une description simple. Par conséquent, une méthode de prise d'empreinte basé sur la signature a attiré de près notre attention. --[signature based approach]-- L'approche basé sur la signature est ce sur quoi nous nous centrons actuellement et qui, nous le croyons sera plus stable, plus fiable et plus flexible méthode de prise d'empreinte ICMP à distance. La méthode basé sur la signature est actuellement basé sur 5 différents tests, qui peuvent optionnellement être inclues dans chaque empreinte de pile de systèmes d'exploitation. Initiallement, les systèmes avec la moindre quantité de tests sont examinés (qui démarre normallement avec un test ICMP unreach). Si aucune pile d'OS trouvée ne correspond à la signature recue, ces piles qui correspondent en partie, étant regroupés encore, et un autre test (basé sur le peu de quantité de tests émis par principe) est choisi et executé. Cette vérification est répétée jusqu'a ce une pile de l'OS, corresponde complètement a la signature trouvée, ou alors les tests s'arretent. Les tests suivants sont actuellement développés: * test ICMP unreachable ( basé sur un port udp fermé, hote unreachable, reseau unreachable (pour les systèmes qui sont pensées etre des gateways) * ICMP echo request/reply test * ICMP timestamp request * ICMP information request * ICMP address mask request --[future implementations/development]-- Les sujets suivants sont prévus d'être développé (nous acceuillons les discussions et suggestions sur ce sujet avec grad plaisir): * fingerprints database (actuellement en phase de test) * Dynamic, AI based logic (projet à long terme :)) * Tests devraient fortement dépendre de la topologie du reseau (pre-test de mapping du reseau auront lieu. * Path-to-target test (pour calculer l'hops distance de la cible) sondage des dispositifs filtrant * Implementations futures utiliseront des paquets avec les données de l'application actuelle pour écarter les chances d'être détectées. * d'autres capacités de mapping de réseau devrait être inclue ( indentification du rôle du reseau, recherche de port UDP fermé, reachability tests, etc). --[code for kids]-- Codes actuellement implémentés et plus de documentation sont disponibles a ces adresses suivantes: http://www.sys-security.com/html/projects/X.html http://xprobe.sourceforge.net http://www.notlsd.net/xprobe/ Ofir Arkin Fyodor Yarochkin |=[ EOF ]=---------------------------------------------------------------=|