Scapy/en

From aldeid
Jump to navigation Jump to search


You might also see: Nemesis

<languages/>

Description

Scapy est un logiciel libre de manipulation de paquets, écrit en langage python. Il est capable, entre autres, d'intercepter le trafic sur un segment réseau, de générer des paquets dans un nombre important de protocoles, de réaliser une prise d'empreinte de la pile TCP/IP, de faire un traceroute et d'analyser le réseau.

Installation

Sous Windows

L'installation de Scapy sous Windows est bien moins triviale que sous Linux.
La procédure d'installation est décrite ici.

Sous Linux (Debian)

Installation par les packages

Il existe un package Scapy. Néanmoins, celui-ci correspond à une ancienne version (1.1.1-3) et il est préférable d’effectuer une installation manuelle. La commande suivante installe scapy ainsi que les dépendances nécessaires :

# apt-get install python-gnuplot python-crypto python-pyx ebtables python-visual sox xpdf gv python-scapy
Note
Pour une installation dans un autre environnement que Debian ou pour plus de renseignements sur les dépendances, consulter la page suivante : http://www.secdev.org/projects/scapy/portability.html.

Installation par les sources

Installation des dépendances

gnuplot (nécessaire pour gnuplot-py)
# cd /usr/local/src/
# wget http://downloads.sourceforge.net/sourceforge/gnuplot/gnuplot-4.2.5.tar.gz?use_mirror=freefr
# tar xzvf gnuplot-4.2.5.tar.gz
# cd gnuplot-4.2.5/
# ./configure
# make
# make install
package pyhton-dev (requis pour numpy)
# apt-get install python-dev
numpy (nécessaire pour gnuplot-py)
# cd /usr/local/src/
# wget http://downloads.sourceforge.net/sourceforge/numpy/numpy-1.3.0.tar.gz?use_mirror=freefr
# tar xzvf numpy-1.3.0.tar.gz
# cd numpy-1.3.0/
# python setup.py install
gnuplot-py
# cd /usr/local/src/
# wget http://downloads.sourceforge.net/sourceforge/gnuplot-py/gnuplot-py-1.8.tar.gz?use_mirror=freefr
# tar xzvf gnuplot-py-1.8.tar.gz
# cd gnuplot-py-1.8/
# python setup.py install
LaTeX
# cd /usr/local/src/
# wget http://ctan.math.utah.edu/ctan/tex-archive/systems/texlive/tlnet/2008/install-tl-unx.tar.gz
# tar xzvf install-tl-unx.tar.gz
# cd install-tl/
# ./install-tl

Suivre les étapes de l'installation

INCOMPLETE SECTION OR ARTICLE
This section/article is being written and is therefore not complete.
Thank you for your comprehension.
************
http://www.secdev.org/projects/scapy/doc/installation.html
************

Utilisation

Remarques générales

  • Le caractère "_" désigne le dernier résultat. Par exemple :
>>> a="Hello"
>>> str(a)
'Hello'
>>> hexdump(_)
0000   48 65 6C 6C 6F         Hello
  • Pour obtenir de l'aide sur une fonction, utilisez la fonction help(nom_de_la_fonction)
>>> help(sniff)
Help on function sniff in module __main__:

sniff(count=0, store=1, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, *arg, **karg)
    Sniff packets
    sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets

       count: number of packets to capture. 0 means infinity
       store: wether to store sniffed packets or discard them
         prn: function to apply to each packet. If something is returned, it is displayed. Ex:
              ex: prn = lambda x: x.summary()
     lfilter: python function applied to each packet to determine if further action may be done
              ex: lfilter = lambda x: x.haslayer(Padding)
     offline: pcap file to read packets from, instead of sniffing them
     timeout: stop sniffing after a given time (default: None)
    L2socket: use the provided L2socket
  • Pour connaître la liste des paramètres d'une couche et les valeurs par défaut de ces paramètres, utilisez : ls(couche). Pour connaître la liste des couches, utilisez ls() sans paramètre. Enfin, pour lister les paramètres d'une variable (par exemple t1=IP(dst="192.168.182.132")), utilisez ls(t1).
>>> ls(IP)
version    : BitField             = (4)
ihl        : BitField             = (None)
tos        : XByteField           = (0)
len        : ShortField           = (None)
id         : ShortField           = (1)
flags      : FlagsField           = (0)
frag       : BitField             = (0)
ttl        : ByteField            = (64)
proto      : ByteEnumField        = (0)
chksum     : XShortField          = (None)
src        : Emph                 = (None)
dst        : Emph                 = ('127.0.0.1')
options    : IPoptionsField       = ()
  • Pour connaître la liste des commandes disponibles, utilisez la fonction lsc().
>>> lsc()
sr               : Send and receive packets at layer 3
sr1              : Send packets at layer 3 and return only the first answer
srp              : Send and receive packets at layer 2
srp1             : Send and receive packets at layer 2 and return only the first answer
srloop           : Send a packet at layer 3 in loop and print the answer each time
srploop          : Send a packet at layer 2 in loop and print the answer each time
sniff            : Sniff packets
p0f              : Passive OS fingerprinting: which OS emitted this TCP SYN ?
arpcachepoison   : Poison target's cache with (your MAC,victim's IP) couple
send             : Send packets at layer 3
sendp            : Send packets at layer 2
traceroute       : Instant TCP traceroute
arping           : Send ARP who-has requests to determine which hosts are up
ls               : List  available layers, or infos on a given layer
lsc              : List user commands
queso            : Queso OS fingerprinting
nmap_fp          : nmap fingerprinting
report_ports     : portscan a target and output a LaTeX table
dyndns_add       : Send a DNS add message to a nameserver for "name" to have a new "rdata"
dyndns_del       : Send a DNS delete message to a nameserver for "name"
is_promisc       : Try to guess if target is in Promisc mode. The target is provided by its ip.
promiscping      : Send ARP who-has requests to determine which hosts are in promiscuous mode
  • Enfin, pour connaître la syntaxe des paramètres propres aux protocoles (src=, dst=, etc.), vous pouvez vous référer à la colonne "abréviation" des tableaux de description des champs dans les paragraphes relatifs aux protocoles, vus dans le paragraphe 2.3.

Initialiser une session

Pour initialiser une nouvelle session, utiliser la commande suivante :

# ./scapy.py -s mysession
INFO: Using session [mysession]
Welcome to Scapy (1.2.0.2)
>>>
Note
Le paramètre optionnel –s nom_de_la_session permet d'enregistrer et de rappeler l'historique des commandes et des objets créés au sein de la session nom_de_la_session. Il est possible d'enregistrer plusieurs sessions.

Forger des paquets

Scapy permet de forger n’importe quel type de paquet (couche TCP, UDP, IP, etc.). Pour chaque couche, les valeurs qui ne sont pas renseignées manuellement le seront automatiquement. La commande ls(IP) permet de consulter l’attribution automatique de ces valeurs.

>>> ls(IP)
version    : BitField             = (4)
ihl        : BitField             = (None)
tos        : XByteField           = (0)
len        : ShortField           = (None)
id         : ShortField           = (1)
flags      : FlagsField           = (0)
frag       : BitField             = (0)
ttl        : ByteField            = (64)
proto      : ByteEnumField        = (0)
chksum     : XShortField          = (None)
src        : Emph                 = (None)
dst        : Emph                 = ('127.0.0.1')
options    : IPoptionsField       = ()
Note
La fonction ls( ) utilisée sans argument permet de lister les couches disponibles. Pour chacune d'entre elle, il est possible de consulter les paramètres.

Initialisons tout d’abord un nouvel objet :

>>> a=IP()

Celui-ci contient dorénavant des valeurs par défaut :

>>> a.ttl
64
>>> a.src
'127.0.0.1'

Il est possible de forcer ces valeurs par défaut :

>>> a.src='192.168.1.13'
>>> a.src
'192.168.1.13'

Pour consulter toutes les valeurs forcées, il suffit de rappeler l’objet :

>>> a
<IP  src=192.168.1.13 |>

Certaines valeurs sont dépendantes et donc recalculées. L’exemple ci-dessous illustre ce phénomène (la valeur de a.src par défaut est mise à jour par dépendance de mise à jour de la valeur de a.dst)

>>> a=IP()
>>> a.src
'127.0.0.1'
>>> a.dst='192.168.1.1'
>>> a.src
'192.168.182.132'

La fonction del( ) permet de détruire tout ou partie d’un objet. L’exemple qui suit montre que la suppression d’une valeur forcée entraîne la réinitialisation de la valeur par défaut :

>>> del(a.dst)
>>> a.dst, a.src
('127.0.0.1', '127.0.0.1')
>>> a
<IP  |>
>>> del(a)
>>> a
Traceback (most recent call last):
  File "<console>", line 1, in ?
NameError: name 'a' is not defined

Pour compléter notre paquet, nous pouvons également spécifier les drapeaux TCP comme suit :

>>> a=IP(dst="192.168.1.1")
>>> a
<IP  dst=192.168.1.1 |>
>>> b=a/TCP(flags="SF")
>>> b
<IP  frag=0 proto=tcp dst=192.168.1.1 |
  <TCP  flags=FS |>>

Ou, pour une vue plus détaillée :

>>> b.show()
###[ IP ]###
  version= 4
  ihl= 0
  tos= 0x0
  len= 0
  id= 1
  flags=
  frag= 0
  ttl= 64
  proto= tcp
  chksum= 0x0
  src= 192.168.182.132
  dst= 192.168.1.1
  options= 
###[ TCP ]###
     sport= ftp_data
     dport= www
     seq= 0
     ack= 0
     dataofs= 0
     reserved= 0
     flags= FS
     window= 8192
     chksum= 0x0
     urgptr= 0
     options= {}

Il est également possible de spécifier plusieurs éléments par paramètre. L'exemple suivant montre comment spécifier deux ports de destination :

>>> b.ttl=(10,14)
>>> b.dport=[80,443]
>>> [k for k in b]
[<IP frag=0 ttl=10 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>,
 <IP frag=0 ttl=10 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>,
 <IP frag=0 ttl=11 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>,
 <IP frag=0 ttl=11 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>,
 <IP frag=0 ttl=12 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>,
 <IP frag=0 ttl=12 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>,
 <IP frag=0 ttl=13 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>,
 <IP frag=0 ttl=13 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>,
 <IP frag=0 ttl=14 proto=tcp dst=192.168.1.1 |<TCP dport=www flags=FS |>>,
 <IP frag=0 ttl=14 proto=tcp dst=192.168.1.1 |<TCP dport=https flags=FS |>>]
Note
Des valeurs distinctes s'écrivent entre crochets [v1,v2,…] et des intervalles entre parenthèses (val_min,val_max).

Envoyer et recevoir des paquets

La commande send( ) permet d'envoyer des paquets précédemment forgés :

>>> a=IP(dst="192.168.225.1")
>>> a
<IP  dst=192.168.225.1 |>
>>> send(a)
.
Sent 1 packets.
Note
La fonction sendp( ) agit sur la couche 3, ce qui signifie que la couche 2 est contrôlée automatiquement par Scapy. Pour envoyer des paquets sur la couche 2, utiliser la fonction sendp( ).

Il existe plusieurs fonctions pour envoyer et recevoir des paquets :

  • La fontion sr( ) émet sur la couche 3 (réseau) et reçoit les réponses;
  • La fonction sr1( ) émet sur la couche 3 (réseau) et renvoie la première réponse;
  • La fonction srp( ) émet sur la couche 2 (liaison) et reçoit les réponses;
  • La fonction srp1( ) émet sur la couche 2 (liaison) et renvoie la première réponse.
>>> sr1(IP(dst="192.168.225.1")/ICMP())
Begin emission:
.*Finished to send 1 packets.
Received 2 packets, got 1 answers, remaining 0 packets
<IP  version=4L ihl=5L tos=0x0 len=28 id=1758 flags= frag=0L ttl=128 proto=icmp
chksum=0x1b2c src=192.168.225.1 dst=192.168.182.132 options= |<ICMP  type=echo
-reply code=0 chksum=0xffff id=0x0 seq=0x0 |<Padding  load='\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' >>>

En cas de non réponse :

>>> sr1(IP(dst="192.168.225.2")/ICMP())
Begin emission:
.Finished to send 1 packets.
..............................................................^C
Received 63 packets, got 0 answers, remaining 1 packets

Il est possible de scanner les hôtes actifs sur un réseau, en exploitant le tableau de résultats comme dans l'exemple ci-dessous :

>>> sr(IP(dst="192.168.0.0/24")/ICMP())
Begin emission:
....*.*.................*.Finished to send 256 packets.
...........^C
Received 37 packets, got 3 answers, remaining 253 packets
(<Results: TCP:0 UDP:0 ICMP:3 Other:0>, <Unanswered: TCP:0 UDP:0 ICMP:253 Other:
0>)
>>> res,unans=_
>>> res.summary()
IP / ICMP 192.168.182.132 > 192.168.0.10 echo-request 0 ==> IP / ICMP 192.168.0.
10 > 192.168.182.132 echo-reply 0 / Padding
IP / ICMP 192.168.182.132 > 192.168.0.13 echo-request 0 ==> IP / ICMP 192.168.0.
13 > 192.168.182.132 echo-reply 0 / Padding
IP / ICMP 192.168.182.132 > 192.168.0.254 echo-request 0 ==> IP / ICMP 192.168.0
.254 > 192.168.182.132 echo-reply 0 / Padding

Mode écoute

Le mode d'écoute est assuré par la fonction sniff( ). Elle accepte comme arguments principaux count pour limiter l'écoute à un nombre de paquets, et filter afin de filtrer le type de paquet (TCP, UDP, ICMP, Other).
Sur le serveur, entrez la commande suivante :

>>> sniff(count=5)

Sur le client, effectuez un ping vers le serveur afin de générer du trafic. Scapy passe alors en mode d'écoute. Lorsque le nombre de paquets spécifiés (ici 5) est atteint, Scapy rend la main et affiche un message :

<Sniffed: TCP:1 UDP:0 ICMP:4 Other:0>

Il est alors possible de déchiffrer le résultat intercepté :

>>> a=_
>>> a.summary()
Ether / IP / TCP 192.168.182.1:1200 > 192.168.182.132:https A / Padding
Ether / IP / ICMP 192.168.182.1 > 192.168.182.132 echo-request 0 / Raw
Ether / IP / ICMP 192.168.182.132 > 192.168.182.1 echo-reply 0 / Raw
Ether / IP / ICMP 192.168.182.1 > 192.168.182.132 echo-request 0 / Raw
Ether / IP / ICMP 192.168.182.132 > 192.168.182.1 echo-reply 0 / Raw

Les fonctions wrpcap( ) et rdpcap( ) permettent respectivement d'écrire et de lire des fichiers de capture.

Conclusion

Scapy est un outil complet qui permet de fabriquer presque n'importe quel type de paquet, ce qui implique également l'émission de paquets malformés, ping de la mort ou autres. C'est pourquoi, même si cet outil connaît certaines limites, il est très utile dans le cadre de campagnes de tests de sécurité d'un réseau.
Par ailleurs, Scapy est doté de fonctionnalités graphiques – non présentées dans le présent document – et qui permettent de représenter les résultats de traceroute en 3D (voir figure suivante : rendu 3D d'un traceroute avec Scapy).