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.
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
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.
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.
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.
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.
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)
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!
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.
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)
.
Client | Fin de connexion coté serveur | Fin 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 |
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.
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
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 !
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.
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.
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
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.
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.
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
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)
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.)
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 SecureFlags TCP
ACK | Acquitte/Confirme la bonne réception |
FIN | Fin de connexion |
OOB | Out of Band, données urgentes |
PSH | Données pour l'application |
RST | Reset, refus ou coupure brutale de connexion |
SYN | Initialisation une connexion |
URG | Paquet urgent |
TCP | Transport Control Protocol : utilisé pour l'échange de données. Par exemple, le surf internet HTTP. |
UDP | User 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. |
ICMP | Internet Control Message Protocol : utilisé pour les messages d'erreurs et autres messages à usage interne de TCP/IP. Exemple d'application : ping ou traceroute. |
IP | Une adresse IP est une adresse Internet sur 4 octets (IPv4). Elle identifie de manière unique chaque machine connectée directement à Internet. |
Port | Numé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. |
Firewall | Dispositif 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. |