HSC
Cabinet de consultants en sécurité informatique depuis 1989 - Spécialisé sur Unix, Windows, TCP/IP et Internet
Mode texte : accès au contenu de la page
Hervé Schauer Consultants
Vous êtes ici : Accueil > Ressources > Brèves > Expresssions BPF avancées
Accéder au : Site HSC des formations
Télécharger le catalogue des formations
Recherche :  
English version
   Services   
o Domaines de compétences
o Conseil & Expertise
o Prestations ISO 27001
o Audit & Évaluation
o Tests d'intrusion
o Tests de vulnérabilités (TSAR)
o Analyse Forensique
o Certification ARJEL
o Formations
o E-learning
   Conférences   
o Agenda
o Interventions passées
o Tutoriels
   Ressources   
o Index thématique
o Brèves
o Présentations
o Cours
o Articles
o Outils (téléchargement)
o Veille en vulnérabilité
   Société   
o Hervé Schauer
o Equipe
o Offres d'emploi
o Références
o Historique
o Partenariats
o Associations
   Presse et
 communication
 
 
o Newsletter HSC
o Bulletin juridique HSC
o Revue de presse
o Communiqués de presse
o Publications
   Contacts   
o Coordonnées
o Requêtes particulières
o Accès à nos locaux
o Hôtels proches de nos locaux
|>|Expresssions BPF avancées  

par Denis Ducamp et Stéphane Aubert (13/12/2000)



Cet article part du principe que vous savez utiliser tcpdump et ses
expressions de base, telles qu'expliquées dans le manuel tcpdump(1), 
il explique quelques filtrages avancés.

Les exemples sont donnés avec tcpdump (sauf un cas avec snort) et utilisent
le fait de pouvoir tester le n-ième octet d'un paquet IP ou de la partie
icmp, udp ou tcp. Il est également possible, grâce à des expressions
binaires de tester un ou plusieurs bits de chaque octet.



1) Intervalles de ports

   A l'aide des expressions, il n'est possible de spécifier à tcpdump qu'un
numéro de port et non pas un intervalle. Il est pourtant possible d'utiliser
quelques fonctions avancées pour contourner ce problème :

 . ports (non) privilégiées :

Un port privilégié doit être dans l'intervalle 1024-65535. De façon plus
simple il est possible de dire qu'il doit être supérieur (strictement) à
1023 .

Le numéro de port source d'un paquet tcp/udp est le nombre constitué par les
deux premiers octets de la partie tcp/udp . Il est possible d'accéder à ce
nombre par l'expression tcp[0:2] et udp[0:2] .

Le numéro de port destination est le nombre constitué par les deux octets
suivants, soit tcp[2:2] et udp[2:2] .

Il est alors possible de filtrer les paquets :

 . avec un port source privilégié : 'tcp[0:2] < 1024 || udp[0:2] < 1024'

# tcpdump -n 'tcp[2:2] > 1023 || udp[2:2] > 1023'
23:06:17.852561 192.168.1.66.1811 > 192.168.1.25.8080: S 1030938166:1030938166(0) win 32120 <mss 1460,sackOK,timestamp 13139100[|tcp]> (DF) [tos 0x10]

 . avec un port destination non privilégié : 'tcp[2:2] > 1023 || udp[2:2] > 1023'

# tcpdump -n 'tcp[2:2] < 1024 || udp[2:2] < 1024'
23:07:42.263851 192.168.1.66.1812 > 192.168.1.25.22: S 1114190849:1114190849(0) win 32120 <mss 1460,sackOK,timestamp 13147541[|tcp]> (DF)

Exemples :

 * Les paquets tcp avec les ports source et destination privilégiés :

# tcpdump -n 'tcp[0:2] < 1024 and tcp[2:2] < 1024'
14:58:51.999794 10.193.56.58.1020 > 192.168.1.33.513: S 2175502554:2175502554(0) win 32120 <mss 1460,sackOK,timestamp 441092436[|tcp]> (DF)

 * Les paquets tcp avec le port destination privilégié mais supérieur à 1010 :

# tcpdump -n 'tcp[2:2] > 1010 and tcp[2:2] < 1024'
18:45:51.590709 192.168.1.25.22 > 192.168.1.88.1021: P 738012345:738012365(20) ack 153592153 win 32120 <nop,nop,timestamp 65176 9178413> (DF) [tos 0x10]

 * Les paquets tcp dont au moins un port, source ou destination, est
   privilégié et supérieur à 1010 :

# tcpdump -n '( tcp[0:2] > 1010 and tcp[0:2] < 1024 ) or ( tcp[2:2] > 1010 and tcp[2:2] < 1024 )'
18:45:51.581313 192.168.1.88.1021 > 192.168.1.25.22: . ack 738012345 win 32120 <nop,nop,timestamp 9178413 65173> (DF) [tos 0x10]

 * Tous les paquets correspondant à une connexion ssh classique
   (port source > 1010 et < 1024) :

# tcpdump -n '( tcp[0:2] > 1010 and tcp[0:2] < 1024 and dst port 22 ) or ( tcp[2:2] > 1010 and tcp[2:2] < 1024 and src port 22 )'
18:45:51.581313 192.168.1.88.1021 > 192.168.1.25.22: . ack 738012345 win 32120 <nop,nop,timestamp 9178413 65173> (DF) [tos 0x10]



2) Début et fin de connexion :

Les débuts de connexion possèdent le bit SYN positionné alors que les fins
de connexion possèdent le bit FIN positionné. Ils sont respectivement les
premier et deuxième bits du treizième octet d'un paquet tcp.

Il n'est pas possible d'effectuer directement un test sur un bit donné, mais
il est possible de tester le résultat d'une expression logique. Ainsi les
expressions :
	'tcp[13] & 2 != 0'
et	'tcp[13] & 1 != 0'
sont respectivement vraies si et seulement si les bits SYN et FIN sont
positionnés.

Exemples :

 * Un paquet tcp avec le bit SYN en destination du port 25 (smtp) :

# tcpdump -n 'dst port 25 and tcp[13] & 2 != 0'
18:45:57.437699 10.207.153.254.4396 > 192.168.1.33.25: S 2645354413:2645354413(0) win 8192 <mss 1460,nop,wscale 0,nop,nop,timestamp[|tcp]> (DF)

Sans le mot clé dst, nous aurions eu les deux premiers paquets de la
connexion :

# tcpdump -n 'port 25 and tcp[13] & 2 != 0'
18:45:57.437699 10.207.153.254.4396 > 192.168.1.33.25: S 2645354413:2645354413(0) win 8192 <mss 1460,nop,wscale 0,nop,nop,timestamp[|tcp]> (DF)
18:45:57.440166 192.168.1.33.25 > 10.207.153.254.4396: S 817842143:817842143(0) ack 2645354414 win 17520 <mss 1460> (DF)

 * Un paquet tcp avec le bit FIN en destination du port 25 (smtp) :

# tcpdump -n 'port 25 and tcp[13] & 1 != 0'
18:46:02.480211 10.207.153.254.4396 > 192.168.1.33.25: F 2645355931:2645355931(0) ack 817842346 win 8760 (DF)

De la même façon il est possible de tester le bit ACK d'un paquet :
	'tcp[13] & 16 != 0'

Exemples :

 * Le deuxième paquet de chaque connexion (bits SYN et ACK présents) :

# tcpdump -n 'port 25 and tcp[13] & 18 = 18'
18:45:57.440166 192.168.1.33.25 > 10.207.153.254.4396: S 817842143:817842143(0) ack 2645354414 win 17520 <mss 1460> (DF)

A noter : 'tcp[13] & 18 = 18' est différente de 'tcp[13] & 18 != 0' car ici
il s'agit de tester la position des deux bits :

 - 'tcp[13] & 18 = 18' correspond à 'tcp[13] & 16 != 0 and tcp[13] & 2 != 0'
   => Le deuxième paquet de chaque connexion

 - 'tcp[13] & 18 != 0' correspond à 'tcp[13] & 16 != 0 or tcp[13] & 2 != 0'
   => Tous les paquets où au moins l'un de ces deux bits est positionné,
      c'est-à-dire tous les paquets TCP sauf ceux qui n'ont aucun de ces
      deux bits positionné

Les autres bits intéressants de ce treizième octet tcp sont :
 - tcp[13] & 4 != 0  : Reset (RST)
 - tcp[13] & 8 != 0  : Push (PSH)
 - tcp[13] & 32 != 0 : Urgent (URG)

3) Intervalle d'adresses

Les intervalles d'adresses ne sont possibles de façon aisée que
 . s'il correspondent à une classe A, B ou C :
	net 192.168.1
   correspondant aux adresses 192.168.1.0 à 192.168.1.255 .
 . s'ils peuvent être exprimés par un masque :
	net 192.168.1.64 mask 255.255.255.224
   correspondant aux adresses 192.168.1.64 à 192.168.1.95 .
 . s'ils peuvent être exprimés par un nombre de bits :
	net 192.168.1.64/27

Pour n'avoir que les adresses 192.168.1.0/27 il faut alors chercher
directement dans les entêtes des paquets. L'adresse source est stockée dans
les octets ip[12:4] et l'adresse destination dans ip[16:4]

Pour avoir tous les paquets à destination de 192.168.1.0/27 :

# tcpdump -n 'dst net 192.168.1 and ip[19] < 32'
18:45:51.581313 192.168.1.88.1021 > 192.168.1.25.22: . ack 738012345 win 32120 <nop,nop,timestamp 9178413 65173> (DF) [tos 0x10]

Pour avoir tous les paquets à destination ou en provenance de 192.168.1.0/27 :

# tcpdump -n '(dst net 192.168.1 and ip[19] < 32) or (src net 192.168.1 and ip[15] < 32)'
13:52:49.259143 192.168.1.25.1047 > 10.207.97.14.21: P 46:54(8) ack 628 win 32120 <nop,nop,timestamp 24226943 365462260> (DF)
13:53:01.694052 10.207.97.14.21 > 192.168.1.25.1047: P 628:644(16) ack 54 win 10136 <nop,nop,timestamp 365463504 24226943> (DF)

Pour avoir tous les paquets à destination de 192.168.1.128/27 :

# tcpdump -n 'dst net 192.168.1 and ip[19] > 127 and ip[19] < 161'
09:39:56.210837 10.137.194.168.22 > 192.168.1.130.1023: S 1644468176:1644468176(0) ack 3105597967 win 8760 <mss 1460> (DF)
09:40:10.237888 10.137.194.168.22 > 192.168.1.130.1023: P 1:16(15) ack 1 win 8760 (DF) [tos 0x10]



4) Paquets fragmentés

L'expression pour tester le bit MF (More Fragments are coming) est :
	ip[6] & 32 != 0
L'expression pour obtenir l'offset d'un paquet est :
	ip[6:2] & 0x1fff != 0

Exemples :

Les fragments à suivre...

# tcpdump -n 'ip[6] & 32 != 0'
13:14:54.544035 10.164.138.11 > 192.168.1.33: icmp: echo request (frag 34819:552@0+)
18:04:56.134138 10.209.1.224.16 > 192.168.1.33.2222: FP 1585299871:1585301027(1156) ack 3991382276 win 8460 (frag 9397:1176@0+)
19:46:14.940188 10.193.250.165 > 192.168.1.33: icmp: echo request (frag 45828:552@0+)
19:46:38.299178 10.193.250.165 > 192.168.1.33: icmp: echo request (frag 3333:552@0+)

Les derniers fragments :

# tcpdump -n 'ip[6] & 32 = 0 and ip[6:2] & 0x1fff != 0'
13:14:54.566670 10.164.138.11 > 192.168.1.33: (frag 34819:156@552)
18:04:55.980888 10.209.1.224 > 192.168.1.33: (frag 9397:26@1176)
19:46:11.290330 10.193.250.165 > 192.168.1.33: (frag 33540:156@552)
19:46:14.962561 10.193.250.165 > 192.168.1.33: (frag 45828:156@552)
19:46:38.321829 110.193.250.165 > 192.168.1.33: (frag 3333:156@552)

Le bit DF (Don't Fragment) peut être testé par l'expression suivante :
	ip[6] & 64 != 0

# tcpdump -n 'ip[6] & 64 != 0'
18:51:54.021579 10.194.158.97.53 > 192.168.1.193.4788: 22755* 0/1/0 (94) (DF)
18:51:54.101659 10.194.158.97.53 > 192.168.1.193.4788: 22756* 3/2/5 (225) (DF)
18:51:54.280052 10.194.73.73.53 > 192.168.1.193.4788: 22757* 0/0/0 (32) (DF)
18:51:54.461284 10.194.73.73.53 > 192.168.1.193.4788: 22758* 2/2/4 (184) (DF)
18:51:54.640693 10.192.93.0.53 > 192.168.1.193.4788: 22766*- 1/3/3 (162) (DF)
18:51:54.665576 10.192.93.0.53 > 192.168.1.193.4788: 22767*- 1/3/3 (162) (DF)
18:51:54.764120 10.192.16.202.53 > 192.168.1.193.4788: 22770 0/2/2 (104) (DF)
18:51:55.182202 10.195.6.58.53 > 192.168.1.193.4788: 22777 NXDomain* 0/1/0 (100) (DF)
18:51:55.327924 10.193.212.1.53 > 192.168.1.193.4788: 22778* 0/1/0 (89) (DF)
18:51:55.652443 10.192.16.202.53 > 192.168.1.193.4788: 22781 3/3/3 (190) (DF)


Dans les paquets IP et TCP, certains bits ne sont pas utilisés et se
trouvent normalement à 0 (c'est pas sécure TCP/IP : il y a des canaux cachés
;-) :

 . le bit 'X' : 'tcp[13] & 64 != 0'

# snort -v 'tcp[13] & 64 != 0'
12/13-22:54:25.387585 192.168.1.66:2118 -> 192.168.1.22:22
TCP TTL:64 TOS:0x0 ID:16944 
2*S***** Seq: 0x676E579F   Ack: 0x57C95F29   Win: 0x200

 . le bit 'Y' : 'tcp[13] & 64 != 0'

# snort -v 'tcp[13] & 64 != 0'
12/13-22:54:28.389897 192.168.1.66:1434 -> 192.168.1.22:22
TCP TTL:64 TOS:0x0 ID:39642 
*1S***** Seq: 0x45C948F0   Ack: 0xB864002   Win: 0x200

 . au moins un des deux bits 'X' et 'Y' : 'tcp[13] & 192 != 0'

 . 'ip[6] & 128 != 0' : je n'ai jamais vu de paquet avec ce bit positionné.



5) Divers

 - land :

  . adresses source et destination égales : ip[12:4] = ip[16:4]

  . ports source et destination égaux : tcp[0:2] = tcp[2:2] or udp[0:2] = udp[2:2]

En général ce sont des paquets udp qui sont envoyés sur un port 7 (echo), 13
(daytime) ou 19 (chargen). Il est possible de simplifier en considérant que
sur le réseau un paquet avec les adresses source et destination égales n'est
pas légitime; de même pour les paquets avec une adresse source égale à
127.0.0.1

 - smurf :

  . l'adresse destination est broadcast : ip[19] = 255 or ip[19] = 0

En général, ce sont des paquets icmp sur l'adresse broadcast à 1 :
11:29:57.848870 212.216.161.29 > 192.168.1.255: icmp: echo request
20:50:58.137012 212.216.161.7 > 192.168.1.255: icmp: echo request
11:06:44.247517 194.112.71.130 > 192.168.1.255: icmp: echo request
11:06:44.840776 194.112.71.130 > 192.168.1.255: icmp: echo request

Bien sur si votre réseau est segmenté alors il faudra surveiller toutes les
adresses réseau et broadcast possibles; par exemple : 0, 63, 64, 127, 128,
191, 192 et 255.



Dernière modification le 12 novembre 2003 à 13:55:00 CET - webmaster@hsc.fr
Mentions légales - Informations sur ce serveur - © 1989-2013 Hervé Schauer Consultants