Paketanalyse mit "netsniff-ng" en detail

Paketanalyse mit "netsniff-ng" en detail

Netzwerkadministratoren treffen häufig auf Probleme, deren Ursachen nicht auf den ersten Blick zu erkennen sind. Dann helfen ihnen oft Analysetools wie »tcpdump« oder »ettercap« weiter. Wer mit solchen Werkzeugen umgeht, profitiert sehr von Hintergrundwissen über ihre Funktionsweise, wie es dieser Artikel am Beispiel von »netsniff‑ng« leicht verständlich präsentiert.

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 .
   ...

PF_PACKET

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.

Abbildung 1: Das Protokoll PF_PACKET ermöglicht es Userspace-Applikationen, den kompletten Netzwerkstack im Kernel zu umgehen.

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.

ARP Cache Poisoning

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.

Abbildung 2: ARP Cache Poisoning: Mit gefälschten ARP-Paketen gelingt es, sich als Man-in-the-Middle zu etablieren.

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.

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023