Table des matières

Scan de ports avec Scapy

Quelques rappels (Linux)

Pour en savoir plus voir la page de Wikipdia : https://fr.wikipedia.org/wiki/Port_(logiciel)

Pour visualiser les ports ouverts d'un hôte et donc connaître les services actifs (en écoute) :

root@debian:~# netstat -tanpu
Connexions Internet actives (serveurs et établies)
Proto Recv-Q Send-Q Adresse locale   Adresse distante    Etat        PID/Program name
tcp        0      0 127.0.0.1:3306   0.0.0.0:*           LISTEN      645/mysqld
tcp        0      0 0.0.0.0:22       0.0.0.0:*           LISTEN      478/sshd
tcp        0      0 127.0.0.1:25     0.0.0.0:*           LISTEN      1087/exim4
tcp        0    464 192.168.1.159:22 192.168.1.196:50264 ESTABLISHED 1119/sshd: root@pts
tcp6       0      0 :::80            :::*                LISTEN      680/apache2
tcp6       0      0 :::22            :::*                LISTEN      478/sshd
tcp6       0      0 ::1:25           :::*                LISTEN      1087/exim4
udp        0      0 0.0.0.0:68       0.0.0.0:*                       692/dhclient
root@debian:~#

Exemple du service SSH (port 22) :

tcp  0    0 0.0.0.0:22       0.0.0.0:*           LISTEN      478/sshd
tcp  0  464 192.168.1.159:22 192.168.1.196:50264 ESTABLISHED 1119/sshd: root@pts
  • la première ligne montre que le port 22 est à l'état LISTEN,
  • La seconde ligne montre une connexion établie (ESTABLISHED)
    • sur le port 22 du serveur 192.168.1.159
    • avec le client 192.168.1.196 sur le port 50264.

Le port 50264 est choisi aléatoirement par le client lors de l'initialisation de la connexion, pour communiquer avec le serveur.

  • Un port TCP ouvert est un port en état LISTEN,
  • Un port UDP est simplement en écoute car UDP ne gère pas l'établissement de connexions.
udp  0    0 0.0.0.0:68       0.0.0.0:*                   692/dhclient
  • Lors d'un scan de ports, on ne visualise que les ports en état LISTEN.
  • Les ports en l'état ESTABLISHED ne peuvent pas être visualisés puisque cela correspond à une communication spécifique entre deux hôtes et un troisième hôte ne peut entrer dans la communication qui a été établie.

Scan de port TCP

Source Wikipedia : https://fr.wikipedia.org/wiki/Transmission_Control_Protocol#.C3.89tablissement_d.27une_connexion Schéma d'établissement d'une connexion TCP :

  1. Le client envoie un segment avec le flag SYN au serveur,
  2. Le serveur lui répond par un segment avec le flag SYN/ACK,
  3. Le client confirme par un segment avec le flag ACK.

Durant cet échange initial, les numéros de séquence des deux parties sont synchronisés :

  1. Le client utilise son numéro de séquence initial dans le champ “Numéro de séquence” du segment SYN (x par exemple),
  2. Le serveur utilise son numéro de séquence initial dans le champ “Numéro de séquence” du segment SYN/ACK (y par exemple) et ajoute le numéro de séquence du client plus un (x+1) dans le champ “Numéro d'acquittement” du segment,
  3. Le client confirme en envoyant un ACK avec un numéro de séquence augmenté de un (x+1) et un numéro d'acquittement correspondant au numéro de séquence du serveur plus un (y+1).

Si le serveur rejette la connexion, il répond avec un segment dont le flag est RESET.

Attributs disponible et valeur par défaut pour le protocole TCP

>>> ls(TCP) 
sport      : ShortEnumField       = (20)
dport      : ShortEnumField       = (80)
seq        : IntField             = (0)
ack        : IntField             = (0)
dataofs    : BitField             = (None)
reserved   : BitField             = (0)
flags      : FlagsField           = (2)
window     : ShortField           = (8192)
chksum     : XShortField          = (None)
urgptr     : ShortField           = (0)
options    : TCPOptionsField      = ({})
>>>

)

Envoi d'un paquet TCP sur le service Web d'un serveur (port 80) avec le flag SYN

>>> paquet =  IP(dst='192.168.1.1') / TCP(sport=55555, dport=80, flags='S')
>>>
>>> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
..*
Received 5 packets, got 1 answers, remaining 0 packets
>>> rep.show()
0000 IP / TCP 192.168.1.159:55555 > 192.168.1.1:http S ==> IP / TCP 192.168.1.1:http > 192.168.1.159:55555 SA / Padding
>>>
>>> rep[0][0][TCP].show()
###[ TCP ]###
  sport= 55555
  dport= http
  seq= 0
  ack= 0
  dataofs= None
  reserved= 0
  flags= S
  window= 8192
  chksum= None
  urgptr= 0
  options= {}
>>>
 rep[0][1][TCP].show()
###[ TCP ]###
  sport= http
  dport= 55555
  seq= 3631598158
  ack= 1
  dataofs= 6
  reserved= 0
  flags= SA
  window= 14600
  chksum= 0x5f04
  urgptr= 0
  options= [('MSS', 1460)]
###[ Padding ]###
     load= 'I5'
>>>

Envoi d'un paquet TCP sur le port 22 d'un serveur alors que le service SSH n'est pas actif

>>> paquet =  IP(dst='192.168.1.100') / TCP(sport=55555, dport=22, flags='S')
>>> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
..*
Received 5 packets, got 1 answers, remaining 0 packets
>>> rep.show()
0000 IP / TCP 192.168.1.159:55555 > 192.168.1.100:ssh S ==> IP / TCP 192.168.1.100:ssh > 192.168.1.159:55555 RA / Padding
>>> rep[0][1][TCP].show()
###[ TCP ]###
  sport= ssh
  dport= 55555
  seq= 0
  ack= 1
  dataofs= 5
  reserved= 0
  flags= RA
  window= 0
  chksum= 0x5262
  urgptr= 0
  options= {}
###[ Padding ]###
     load= '\x00\x00\x00\x00\x00\x00'
>>>
>>> rep[0][1][TCP].flags
20
>>> 

Préciser plusieurs ports

Il est possible d'utiliser une liste de valeurs pour les attributs des protocoles sous la forme :

Scan de port UDP

Rappel : Un port UDP est simplement en écoute car UDP ne gère pas l'établissement de connexions.

Exemple de scan UDP pour déterminer si le service DNS est actif sur un hôte (en écoute)

Les paramètres à utiliser

Deux réponses sont possibles :

>>> paquet =  IP(dst='192.168.1.1') / UDP(dport=53) / DNS()
>>> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
..*
Received 5 packets, got 1 answers, remaining 0 packets
>>> rep.show()
0000 IP / UDP / DNS Qry  ==> IP / UDP / DNS Ans  / Padding
>>> paquet =  IP(dst='192.168.1.100') / UDP(dport=53) / DNS()
>>> rep, non_rep = sr(paquet)
Begin emission:
..Finished to send 1 packets.
.*
Received 4 packets, got 1 answers, remaining 0 packets
>>> rep.show()
0000 IP / UDP / DNS Qry  ==> IP / ICMP 192.168.1.100 > 192.168.1.159 dest-unreach port-unreachable / IPerror / UDPerror
>>>

Retour à Python : la bibliothèque Scapy ...