Das Tool »netsniff‑ng« ist noch recht jung, es existiert erst seit Sommer 2009. Von Anfang an hob es sich dadurch ab, dass es als erstes Projekt eine spezielle Kerneltechnik verwendete, die so genannten Zero-Copy Receive-Ringe (RX_ RING). Darüber hinaus ist »netsniff‑ng« im Unterschied zu den meisten üblichen Sniffern auch nicht gegen spezielle Bibliotheken wie »libpcap« gelinkt, sondern hängt allein von der »libc« ab, sodass die Installation sehr einfach ist.
Die Bedienung des Programms, das generell mit Rootrechten zu starten ist, bereitet keine Schwierigkeiten. So genügt der Befehl
netsniff‑ng ‑‑dev eth0
um sämtlichen Verkehr auf dem Netzwerkdevice »eth0« zu belauschen und anzuzeigen. Will man lediglich Einsicht in den ausgehenden Netzwerkverkehr, reicht:
netsniff‑ng ‑‑dev eth0 ‑‑type outgoing
Meist ist aber nur ein Teil des gesamten Verkehrs von Interesse, sodass man durch Angabe von sogenannten Berkeley Packet Filter Files (Erläuterung folgt unten) unerwünschte Ausgaben unterdrücken kann:
netsniff‑ng ‑‑dev eth0 ‑‑filter /etc/netsniff-ng/rules/http.bpf
Wo unverschlüsselt kommuniziert wird, lassen sich so wie in Listing 1 sehr leicht Passwörter abhören. Gefahr besteht vor allem, wenn Angreifer zu einem Mittel wie ARP Cache Poisoning greifen, direkt auf dem Gateway lauschen können oder das Netzwerk altertümliche Hub-Hardware benutzt.
Listing 1: SIP-Anruf via Ekiga belauscht
# netsniff‑ng ‑‑dev eth0 ‑‑filter ./sip.bpf netsniff‑ng 0.5.5.0 ‑‑ pid (22158)
nice (0), scheduler (0 prio 0) 1 of 1 CPUs online, affinity bitstring (1)
Parsing rulefile ./sip.bpf (000) ldh [12] (001) jeq #0x800 jt 2 jf 14 ...
‑‑‑ Listening ‑‑‑
...
> 1145 Byte, Unix TS (1288910994 s 404624 us), Thu Nov 4 23:49:54 2010 [ MAC (00:30:05:23:aa:21 => 00:23:69:11:cf:ff), Proto (0x0800, IPv4) ] [ Vendor (Fujitsu Siemens Computers => Cisco‑Linksys, LLC) ] [ IPv4 Addr (192.168.1.108 => 84.14.262.43), Proto (17), TTL (64), TOS (0), Ver (4), IHL (1280), Tlen (1131), ID (0), Res: 0 NoFrag: 1 MoreFrag: 0 offset (0), Chsum (0x7c0a) is ok ] [ UDP Port (5060 => 5060, sip), Len (1111), Chsum (0xa006) ] [ Payload hex (49 4e 56 49 54 45 20 73 69 70 3a 35 30 30 40 65 6b 69 67 61 2e 6e 65 74 20 53 49 50 2f 32 2e 30 0d 0a 44 61 74 65 3a 20 54 ... ] [ Payload char (I N V I T E s i p : 5 0 0 @ e k i g a . n e t S I P / 2 . 0 . . D a t e : T h u , 0 4 N o v 2 0 1 0 2 2 : 4 9 : 5 3 G M T . . C S e q : 1 I N V I T E . . V i a : S I P / 2 . 0 / U D P 1 4 1 . 1 1 . 1 5 9 . 2 5 : 5 0 6 0 ; b r a n c h = z 9 h G 4 b K 2 0 f 3 b f 8 1 ‑ d 3 e 6 ‑ d f 1 1 ‑ 9 f 3 e ‑ 0 0 3 0 0 5 4 1 b 9 7 3 ; r p o r t . . U s e r ‑ A g e n t : E k i g a / 3 . 2 . 7 . . F r o m : " D a n i e l B o r k m a n n " < s i p : d a n i e l . b o r k m a n n @ e k i g a . n e t > ; t a g = 8 2 2 6 b c 8 1 ‑ d 3 e 6 ‑ d f 1 1 ‑ 9 f 3 e ‑ 0 0 3 0 0 5 4 1 b 9 7 3 . . C a l l ‑ I D : 6 e 2 b b c 8 1 ‑ d 3 e 6 ‑ d f 1 1 ‑ 9 f 3 e ‑ 0 0 3 0 0 5 4 1 b 9 7 3 @ h t p c . . T o : < s i p : 5 0 0 @ e k i g a . n e t > . . C o n t a c t : < s i p : d a n i e l . b o r k m a n n @ 1 4 1 . 1 1 . 1 5 9 . 2 5 > . . A l l o w : I N V I T E , A C K , O P T I O N S , B Y E , C A N C E L , S U B S C R I B E , N O T I F Y , R E F E R , M E S S A G E , I N F O , P I N G . . C o n t e n t ‑ T y p e : a p p l i c a t i o n / s d p . . C o n t e n t ‑ L e n g t h : 5 2 5 . ...
In vielen Fällen dient »netsniff‑ng« als Frontend für fortgeschrittene Fähigkeiten des Linux-Kernels. Um rohe Paketdaten aber überhaupt vom Kernel in den Userspace transferieren zu können, braucht man einen speziellen Sockettyp und das Protokoll PF_PACKET. PF_PACKET ermöglicht Userspace-Anwendungen das Empfangen und Versenden von Paketen auf unterster Netzwerkebene und umgeht damit den kompletten Netzwerk-Stack des Kernels wie in Abbildung 1 dargestellt.
Das bedeutet, dass die Applikation Pakete direkt in die TX-Queue des Netzwerkschedulers einreihen kann, die sie dann an den NIC-Gerätetreiber weiterleitet. PF_PACKET unterstützt zwei unterschiedliche Sockettypen, SOCK_DGRAM und SOCK_RAW. Ersterer überlässt dem Kernel noch die Aufgabe, Ethernet-Header selbst zu verwalten. Letzterer dagegen gibt der Userspace-Anwendung die komplette Kontrolle über den Frame. Genau von diesem Typ macht auch »netsniff‑ng« Gebrauch.
Neben dem Sockettyp ist ferner die Angabe eines Ethernet Protokoll-Identifiers nötig, den »/include/linux/if_ether.h« definiert. Der am häufigsten verwendete Identifier ist »ETH_P_IP«, der IPv4-Pakete an die Applikation durchreicht. Da er jedoch das Mitschneiden etlicher interessanter Pakete (beispielsweise ARP) ausschließt, sind in der Implementierung von »netsniff‑ng« alle Protokoll-Identifier mittels der Option »ETH_P_ALL« zugelassen.
Die »PF_PACKET«-Protokollfamilie erlaubt den Zugriff auf Frames, deren Ziel-MAC-Adresse der Adresse der eigenen Netzwerkschnittstelle entspricht. Pakete, deren Ziel andere als die eigene MAC-Adresse sind, verwirft die Netzwerkkarte im Normalfall. Diese Arbeitsweise nennt sich Non-promiscuous Mode. Ausnahmen sind Broadcasts sowie Multicasts.
Im so genannten Promiscuous Mode überprüft die Netzwerkkarte dagegen die MAC-Zieladresse nicht mehr anhand einer Bitmaske. Dadurch treffen alle Frames am Interface ein und werden nun nicht mehr verworfen, falls der Adressat ein anderer ist.
Bekanntlich leitet ein Switch im Unterschied zu einem Hub ein Netzwerkpaket nicht mehr an alle, sondern nur noch an den Port weiter, der mit dem Rechner verbunden ist, dessen MACAdresse mit der Ziel-MAC-Adresse des Pakets übereinstimmt. Dafür führt er intern eine so genannte Source-Address-Table, die die MACAdressen mit zugehöriger physikalischer PortAdresse abspeichert. Diese Tabelle wird bereits durch Abfangen der ARP-Pakete ausreichend gefüllt. Sobald jedoch eine Zieladresse keinem Port zugeordnet werden kann (auch als Lernphase bezeichnet), flutet der Switch sämtliche Ports mit dem entsprechendem Frame und speichert bei einer Rückantwort den Quellport.
Das ARP Cache Poisoning umgeht diesen Mechanismus. Dabei werden die ARP-Tabellen durch explizit gefälschte ARP-Requests (sogenanntes Gratuitous ARP) aktualisiert, sodass Pakete an andere Empfänger umgeleitet werden. Abbildung 2 zeigt den beispielhaften Ablauf dieses Verfahrens. Mallory sendet dabei gefälschte ARP-Pakete an beide Kommunikationspartner, sodass sich ihre internen ARP-Tabellen sowie die des Switches aktualisieren. Möchte daraufhin Bob eine Nachricht an Alice senden, so wird diese tatsächlich an Mallory gesendet, der die Daten mitliest und das Paket an Alice weiterleitet.
In den bisherigen Beispielen wurden alle Pakete in den Userspace weitergereicht. Es wäre nun trivial direkt mit ihren Bytes zu arbeiten und beispielsweise mittels »memcmp« gewünschte Pakete auszuwählen. Das würde zwar funktionieren, wäre aber sehr ineffizient. Um zu entscheiden, ob ein bestimmtes Paket erwünscht ist oder nicht, müsste man es erst komplett vom Kernel in den Userspace-Adressraum kopieren. Diese Operation ist jedoch äußerst zeitaufwendig. Bei hoher Bandbreitennutzung würden ständig Kontextwechsel und Kopieroperationen auftreten, was mit hoher Wahrscheinlichkeit zum Verwerfen von Paketen am Socketdeskriptor führen würde.