==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 <ofir@sys-security.com>
Fyodor Yarochkin <fygrave@tigerteam.net>
|=[ EOF ]=---------------------------------------------------------------=|