Le scan de port

Le scan de port est une technique de base du pirate en herbe ou de l'administrateur réseau pour vérifier quels sont les ports en écoute sur un de ses serveurs. Cet article fera le point sur les différentes techniques actuellement disponibles, puis sur les méthodes permettant d'éviter la détection. Afin d'éviter de scanner inutilement une machine éteinte, il convient de vérifier, au préalable, sa disponibilité. Le scanner envoie un ping, paquet ICMP echo-request, et attend une réponse, un paquet ICMP echo-reply. Il peut aussi contacter un port TCP, généralement le port 80 correspondant au service HTTP, et attendre un acquittement signifiant que la connexion est acceptée ou un reset signalant une connexion est refusée. Dans les deux cas, on comprend que la machine répond. Cette dernière technique peut aussi utiliser un paquet UDP et attendre un "ICMP port unreachable", message indiquant que le port est injoignable.

Les bases de TCP

Le scan TCP connect consiste à demander une connexion sur chacun des ports à scanner. Si la connexion réussie, le port est ouvert. Le scanner n'a plus qu'à interrompre la connexion. Le problème est que ce scan déclenche le logiciel en face en écoute sur ces ports. Ce logiciel peut donc enregistrer une connexion depuis la machine de scan et s'étonner de la fermeture immédiate de celle-ci. Par exemple, voici le message enregistré par un serveur ssh lorsqu'il est ainsi scanné :

Jul  6 18:54:32 p500 sshd[2446]: Did not receive identification string from  172.18.100.1.

Certains scanners ont voulu éviter ce genre de message et renvoient le message QUIT pour clore une connexion SMTP ou FTP. Mais un serveur SSH, par exemple, s'en étonnera:

Jul  6 18:58:03 p500 sshd[2490]: Bad protocol version identification 'QUIT' from 127.0.0.1

La connexion

Initialisation d'une connexion TCP

 Client            Serveur
 
 1 SYN seq=x -->
 
 2           <--  SYN seq=y, ACK x+1
 
 3 ACK y+1   -->

Il s'agit du three-way handshake , phase d'initialisation d'une connexion TCP gérée directement par le système d'exploitation. La première protection du three-way handshake contre l'IP spoofing (lire Pirates Mag' XXX) est que la machine dont l'IP serait usurpée va réagir à la réception du SYN/ACK. N'étant pas à l'origine de la connexion, elle va y mettre fin en envoyant un paquet RST.

Une protection naturelle contre l'IP spoofing

Voici une tentative de connexion au serveur d'un pirate se faisant passer pour le client.

  Pirate
1 IP src=IP Client --> Serveur
  SYN seq=x
-------------------------------------------------
                       Serveur              
2                      SYN seq=y --> Client
                       ACK x+1
-------------------------------------------------
3                      Serveur <-- Client
                                      RST
-------------------------------------------------

La tentative d'IP spoofing a donc échouée. Pour le moment... Le pirate doit donc éviter que le client ne puisse envoyer ce paquet RST.

Les limites de cette protection

L'attaque de Mitnick en 1995 a utilisé un SYN Flood pour empêcher le client de réagir temporairement. Il a donc envoyé de nombreux paquets avec l'indicateur SYN pour submerger le client de demande de connexion. Victime de ce DoS (lire Pirates Mag' XXX), le client est resté muet. La seconde sécurité du three-way handshake réside dans le numéro de séquence.

-------------------------------------------
1 Pirate
  DoS du client  ------------------> Client
-----------------------------------------
2 Pirate  
  ip src=ip client --> Serveur
  syn seq=x
-----------------------------------------
                       Serveur
3                      syn seq=y --> Client
                       ack x+1
-----------------------------------------
     Pirate
4    ack y'+1   ---->  Serveur
     où y' est la
     valeur estimée
     de y.
-----------------------------------------

Pour être en mesure de prédire le numéro de séquence, il faut établir plusieurs connexions rapprochées sur le serveur de façon à obtenir quelques numéros de séquences et en déduire une progression mathématique. Un système d'exploitation doit utiliser un algorithme de génération aléatoire suffisamment robuste pour échapper à cette prédiction.

Une connexion réelle

Voici une capture réseau d'une connexion de la machine 192.168.1.59 sur le port SSH, TCP 22, du serveur 192.168.1.30 :

19:56:34.022780 192.168.1.59.39757 > 192.168.1.30.ssh: S 1097598031:1097598031(0) win 5840 <mss 1460,sackOK,timestamp 20901000,nop,wscale 0> (DF) [tos 0x10]
19:56:34.023234 192.168.1.30.ssh > 192.168.1.59.39757: S 911044868:911044868(0) ack 1097598032 win 5792 <mss 1460,sackOK,timestamp 172232 2090100,nop,wscale 0> (DF)

19:56:34.023277 192.168.1.59.39757 > 192.168.1.30.ssh: . ack 1 win 5840 <nop,nop,timestamp 2090100 172232> (DF) [tos 0x10]

Il s'agit de la traduction réseau de la demande de connexion du logiciel client. C'est un peu plus difficile à lire que sur le schéma... En langage C, une connexion réseau s'établie ainsi: status=connect(socket,(struct sockaddr *)&address,sizeof(address));

Dès réception du paquet avec l'indicateur ACK, le système d'exploitation réveille le logiciel serveur.

Envoi de donnée

Dans le cas présent, le serveur SSH envoie immédiatement sa banner (invite). La banner ou invite en français est le texte affiché automatiquement lors de la connexion par certains protocoles (smtp, ftp, ssh...)

telnet 192.168.1.30 ssh
Trying 192.168.1.30...
Connected to localhost.
Escape character is '^]'.
SSH-2.0-OpenSSH_3.1p1

Cela se traduit au niveau réseau par un paquet avec l'indicateur PUSH.

19:56:34.028053 192.168.1.30.ssh > 192.168.1.59.39757: P 1:26(25) ack 1 win 5792 <nop,nop,timestamp 172233 2090100> (DF)

Absence de service TCP

Si le port destination est fermé parce qu'aucun logiciel n'est à l'écoute sur ce port, le serveur renvoie en 2 un paquet avec l'indicateur RST, un reset.

---------------------------
  Client
1 SYN seq=x  --> Serveur
---------------------------

2 Client <-- Serveur
             RST, ACK x+1
---------------------------
20:07:17.714071 192.168.1.59.39766 > 192.168.1.30.24: S 1748713080:1748713080(0) win 5840 <mss 1460,sackOK,timestamp 21544690,nop,wscale 0> (DF) [tos 0x10]
20:07:17.715006 192.168.1.30.24 > 192.168.1.59.39766: R 0:0(0) ack 1748713081 win 0 (DF) [tos 0x10]

Si vous avez pu suivre ces échanges de paquets, vous êtes pret à découvrir les véritables techniques de scan de port!

TCP syn scan

Une connexion TCP n'étant pas discrète, des personnes ont imaginé de ne pas mener à terme la connexion pour éviter que le logiciel serveur ne se réveille : il suffit de ne jamais envoyer le paquet avec l'indicateur ACK. Le scanner doit fonctionner directement au niveau IP, et non plus au niveau applicatif, pour forger ses propres paquets. Il devra prendre garde à ne pas attendre indéfiniment le second paquet, celui-ci pouvant ne jamais arriver si sa demande de connexion SYN s'est perdue sur le réseau ou si un firewall l'a bloqué. Cette technique est appelée SYN scan, du nom du paquet envoyé, ou half scan, car la connexion est à demi-ouverte. Le système d'exploitation de la machine scannée va attendre le troisième paquet pendant un certain temps en renvoyant plusieurs fois le SYNACK au cas où il se serait perdu.

Extrait de la commande netstat, programme affichant le status des connexions réseaux :

Proto Recv-Q Send-Q Adresse locale          Adresse distante        Etat
tcp        0      0 0.0.0.0:22              0.0.0.0:*              LISTEN
tcp        0      0 192.168.1.30:22         192.168.1.59:49748     SYN_RECV

Voici une capture réseau réalisée avec le sniffer tcpdump (disponible sur www.tcpdump.org ou en standard avec la majorité des Unix). A chaque fois, l'intervalle de temps entre les retransmissions double.

19:46:13.690770 192.168.1.59.49748 > 192.168.1.30.ssh: S 2328184022:2328184022(0) win 1024
19:46:13.691201 192.168.1.30.ssh > 192.168.1.59.49748: S 235163240:235163240(0) ack 2328184023 win 5840 <mss 1460> (DF)
19:46:17.287550 192.168.1.30.ssh > 192.168.1.59.49748: S 235163240:235163240(0) ack 2328184023 win 5840 <mss 1460> (DF)
(suivi de quatre autres retransmissions)

Si le scanner veut être sympathique avec le système d'exploitation, il peut envoyer un reset pour éviter ces retransmissions.

Méthodes furtives

L'indicateur FIN

Une demande logicielle de coupure de la connexion se traduit au niveau réseau par l'utilisation de l'indicateur FIN. En terme de programmation, cela correspond à la fermeture de la socket demandée par le programme, soit en langage C, close(socket).

ClientFin de connexion coté serveurFin de connexion coté client
Commande telnet
telnet smt02003.global-asp.net smtp
Trying 194.51.152.249...
Connected to smt02003.
Escape character is '^]'.
220 smt02003.global-asp.net ESMTP
QUIT
221 Bye
Connection closed by foreign host.
telnet smt02003.global-asp.net smtp
Trying 194.51.152.249...
Connected to smt02003.
Escape character is '^]'.
220 smt02003.global-asp.net ESMTP
^]
telnet> Connection closed.
Capture réseau
Ouverture de la connexion :

 77.975791 172.18.100.49 -> 194.51.152.249 TCP 1232 > 25 [SYN] Seq=571853312 Ack=0 Win=5840 Len=0
 77.976739 194.51.152.249 -> 172.18.100.49 TCP 25 > 1232 [SYN, ACK] Seq=708841229 Ack=571853313 Win=5840 Len=0
 77.976863 172.18.100.49 -> 194.51.152.249 TCP 1232 > 25 [ACK] Seq=571853313 Ack=708841230 Win=5840 Len=0

Echanges de données :

 77.979449 194.51.152.249 -> 172.18.100.49 SMTP Response: 220 smt02003.global-asp.net ESMTP
 77.979548 172.18.100.49 -> 194.51.152.249 TCP 1232 > 25 [ACK] Seq=571853313 Ack=708841265 Win=5840 Len=0
 79.280944 172.18.100.49 -> 194.51.152.249 SMTP Command: QUIT
 79.281524 194.51.152.249 -> 172.18.100.49 TCP 25 > 1232 [ACK] Seq=708841265 Ack=571853319 Win=5840 Len=0
 79.281621 194.51.152.249 -> 172.18.100.49 SMTP Response: 221 Bye
 79.281725 172.18.100.49 -> 194.51.152.249 TCP 1232 > 25 [ACK] Seq=571853319 Ack=708841274 Win=5840 Len=0

Fermeture de la connexion :

 79.281873 194.51.152.249 -> 172.18.100.49 TCP 25 > 1232 [FIN, ACK] Seq=708841274 Ack=571853319 Win=5840 Len=0
 79.293253 172.18.100.49 -> 194.51.152.249 TCP 1232 > 25 [FIN, ACK] Seq=571853319 Ack=708841275 Win=5840 Len=0
 79.293830 194.51.152.249 -> 172.18.100.49 TCP 25 > 1232 [ACK] Seq=708841275 Ack=571853320 Win=5840 Len=0
Comme précédemment, la connexion s'établie :

 39.840251 172.18.100.49 -> 194.51.152.249 TCP 1231 > 25 [SYN] Seq=517473305 Ack=0 Win=5840 Len=0
 39.841217 194.51.152.249 -> 172.18.100.49 TCP 25 > 1231 [SYN, ACK] Seq=683064550 Ack=517473306 Win=5840 Len=0
 39.841340 172.18.100.49 -> 194.51.152.249 TCP 1231 > 25 [ACK] Seq=517473306 Ack=683064551 Win=5840 Len=0

Le serveur de mail envoie sa banner :

 39.843876 194.51.152.249 -> 172.18.100.49 SMTP Response: 220 smt02003.global-asp.net ESMTP
 39.843978 172.18.100.49 -> 194.51.152.249 TCP 1231 > 25 [ACK] Seq=517473306 Ack=683064586 Win=5840 Len=0

Le client interrompt la connexion :

 43.812903 172.18.100.49 -> 194.51.152.249 TCP 1231 > 25 [FIN, ACK] Seq=517473306 Ack=683064586 Win=5840 Len=0
 43.813879 194.51.152.249 -> 172.18.100.49 TCP 25 > 1231 [FIN, ACK] Seq=683064586 Ack=517473307 Win=5840 Len=0
 43.813995 172.18.100.49 -> 194.51.152.249 TCP 1231 > 25 [ACK] Seq=517473307 Ack=683064587 Win=5840 Len=0
Schéma simplifié
1 Client <-- Serveur
             FIN seq=x

2 Client
  FIN seq=y --> Serveur
  ACK x+1

3 Client   <-- Serveur
               ACK y+1
1 Client   --> Serveur
  FIN seq=x

2 Client   <-- Serveur
               FIN seq=y
	       ACK x+1

3 Client   --> Serveur
  ACK y+1

FIN scan

La méthode de FIN scan consiste à envoyer un paquet avec l'indicateur FIN, c'est-à-dire une demande de coupure de connexion. Comme aucune connexion n'est en cours, ce paquet n'a pas lieu d'être. La norme, le RFC 793 (document disponible sur www.faqs.org/rfcs/rfc793.html), indique que le système doit renvoyer un reset si le port est fermé et ignorer ce paquet si le port est ouvert.

Port ouvert

22:16:15.672547 192.168.1.59.61298 > 192.168.1.30.ssh: F 0:0(0) win 3072
22:16:15.975597 192.168.1.59.61299 > 192.168.1.30.ssh: F 0:0(0) win 3072

Port fermé

22:18:20.410031 192.168.1.59.36331 > 192.168.1.30.telnet: F 0:0(0) win 2048
22:18:20.410372 192.168.1.30.telnet > 192.168.1.59.36331: R 0:0(0) ack 1 win 0 (DF)

Malheureusement, Microsoft a du mal avec les standards et Windows renvoie systématiquement un reset quel que soit l'état du port !

L'indicateur URG

Lors d'une communication, les données à envoyer sont placées dans un buffer (mémoire tampon) par le système d'exploitation source et sont envoyées à la destination selon le principe FIFO (First In, First Out ou premier arrivé, premier parti). Pour des raisons diverses, il peut être nécessaire d'envoyer des données de manière urgente sans attendre que le buffer d'émission soit vide. Cela peut être le cas lorsque le client veut interrompre rapidement un flot de données lui parvenant. Le programme du client va envoyer les données urgentes dans un canal hors bande (OOB ou Out Of Band). En langage C, cela peut s'écrire : res=send(socket, "STOP", 4, MSG_OOB); Au niveau réseau, un drapeau URG (urgent) est positionné sur le paquet.

Xmas Tree scan

L'idée est d'envoyer un paquet avec les indicateurs FIN, PUSH et URG. Comme dans le cas du FIN scan, le serveur doit ignorer ce paquet si le port est ouvert et de rejeter la connexion sinon.

Port ouvert

22:22:34.373019 192.168.1.59.49632 > 192.168.1.30.ssh: FP 0:0(0) win 2048 urg 0
22:22:34.675592 192.168.1.59.49633 > 192.168.1.30.ssh: FP 0:0(0) win 2048 urg 0

Port fermé

22:23:39.663022 192.168.1.59.34933 > 192.168.1.30.telnet: FP 0:0(0) win 1024 urg 0
22:23:39.663392 192.168.1.30.telnet > 192.168.1.59.34933: R 0:0(0) ack 1 win 0 (DF)

Encore une fois, cette technique de scan ne fonctionne pas contre des machines sous Windows.

Null scan

Le scanner envoie un paquet qui, cette fois-ci, ne doit comporter aucun indicateur. Le système distant doit se comporter comme dans le cas précédent, sauf s'il s'agit d'un Windows.

Port ouvert

22:24:56.585076 192.168.1.59.51796 > 192.168.1.30.ssh: . win 2048
22:24:56.885602 192.168.1.59.51797 > 192.168.1.30.ssh: . win 2048

Port fermé

22:25:18.554849 192.168.1.59.35260 > 192.168.1.30.telnet: . win 3072
22:25:18.555218 192.168.1.30.telnet > 192.168.1.59.35260: R 0:0(0) ack 0 win 0 (DF)

Recherche du protocole

Un scanner peut faire bien plus que rechercher les ports ouverts. Il peut aussi capturer l'invite s'il y en a une, par exemple, celle d'un serveur de messagerie. Dans le cas de serveur Unix, il peut interroger le service ident/auth (port TCP 113) pour connaître le compte utilisateur sous lequel tourne le logiciel serveur. Enfin, il peut envoyer des requêtes RPC (Remote Procedure Call) pour détecter si le port correspond à un service RPC comme NIS, équivalent d'un contrôleur de domaine sous Unix, ou NFS, partage de disque Unix. Cela est bien utile car les services RPC n'utilisent pas de ports prédéfinis. Des outils annexes permettent de tester des dizaines de protocoles pour identifier celui qui est utilisé (SSL, SSH, POP, IMAP, http, etc.)

Dissimulation

En 1995, une technique, le FTP bounce scan, a été découverte pour scanner des machines en passant par un serveur FTP vulnérable. La même chose est possible via des proxy Internet mal configurés. Plus réaliste, le scanner peut forger des paquets avec de fausses adresses IP source. A condition que les routeurs ne fassent pas de filtrage sur la source, le serveur destination ne pourra pas distinguer quelle est la véritable adresse IP du pirate parmi les différentes adresses sources générées par le scanner.

Christophe GRENIER grenier@cgsecurity.org
Consultant Sécurité chez Global Secure
Flags TCP
ACKAcquitte/Confirme la bonne réception
FINFin de connexion
OOBOut of Band, données urgentes
PSHDonnées pour l'application
RSTReset, refus ou coupure brutale de connexion
SYNInitialisation une connexion
URGPaquet urgent
Lexique
TCPTransport Control Protocol : utilisé pour l'échange de données. Par exemple, le surf internet HTTP.
UDPUser Datagram Protocol : utilisé pour l'envoi de message réseau ou de petit volume de données. La bonne réception du message n'est pas gérée. Par exemple, la résolution de nom DNS.
ICMPInternet Control Message Protocol : utilisé pour les messages d'erreurs et autres messages à usage interne de TCP/IP. Exemple d'application : ping ou traceroute.
IPUne adresse IP est une adresse Internet sur 4 octets (IPv4). Elle identifie de manière unique chaque machine connectée directement à Internet.
PortNuméro utilisé dans les protocoles TCP ou UDP, spécifique à l'application que l'on cherche à contacter, sur une machine identifiée par une adresse IP donnée. Un port d'un serveur est dit ouvert s'il est en attente de connexion, fermé dans le cas contraire.
FirewallDispositif de sécurité réseau filtrant les ports TCP/UDP accessibles ainsi que les différents protocoles utilisables (ICMP par exemple)
Sniffer Logiciel de capture de trame réseau. Permet de surveiller les communications ou d'auditer un réseau.
Socket Terme de programmation système désignant le descripteur d'une communication, ici de type réseau. (Pour un fichier, on parle généralement de handle)
scanner Un scanner est un outil permettant de détecter les ports réseau en écoute sur un serveur.