Aus Linux-Magazin 08/2005

Gefahren im TCP-Protokoll: Angreifer kappen fremde Verbindungen

Per RST-Angriff ist es leicht, fremde TCP-Verbindungen abzuschießen – viel leichter als Experten 20 Jahre lang vermuteten. Gefährdet sind besonders Anwendungen, die auf langlebige TCP-Verbindungen angewiesen sind, etwa VPNs, DNS-Zonentransfers oder BGP. Das Risiko lässt sich aber minimieren.

Dass das Transmission Control Protocol (TCP) unsicher arbeitet, ist spätestens seit 1985 bekannt (siehe Kasten “Historie”). Ein Angreifer kann bestehende TCP-Verbindungen abbrechen, korrumpieren oder übernehmen (so genanntes Hijacking). Dazu genügen ihm wenige Informationen über die Verbindung: Quell- und Ziel-IP-Adresse, Quell- und Ziel-Port und eine gültige Sequenznummer. Kann er die Verbindung abhören, hat er bereits gewonnen.

Gelingt ihm das nicht, weil er keinen Rechner auf dem Weg zwischen Client und Server kontrolliert, wird es schwieriger. Allerdings wurde der Aufwand, den ein Saboteur treiben muss, lange Zeit überschätzt: Einige Tricks mit dem Windowing von TCP erleichtern die Manipulationen aus der Ferne enorm.

Schwierig ist es vor allem, die richtigen Sequenznummern zu erraten. Nur damit hält der Zielrechner die eingeschleusten IP-Datagramme für Pakete, die zur bestehenden TCP-Verbindung gehören. Hat der Angreifer passende Werte gefunden, hindert ihn nichts mehr daran, Daten in eine bereits bestehende Verbindung einzuschleusen und damit zum Beispiel unerlaubt Zugriff auf Informationen zu erlangen oder ganze Verbindungen durch Senden eines Pakets mit gesetztem Reset-Flag (RST) zu beenden.

Oft ist dieser Reset nur lästig, etwa beim Surfen im Web. In anderen Szenarien führt er zu schweren Problemen: Hohe Kosten verursacht zum Beispiel eine wiederholt unterbrochene BGP-Verbindung (siehe Kasten “Wichtige Begriffe”) zwischen zwei zentralen Routern des Internet. Mit einem solchen Denial-of-Service-Angriff (DoS) in der Hinterhand ist sogar Schutzgelderpressung möglich: Nur wer zahlt, kann seine Server weiterhin störungsfrei betreiben.

Aber auch für kleinere Firmennetzwerke birgt ein DoS-Angriff erhebliches Risikopotenzial. Sollten Kriminelle einen Onlineshop für längere Zeit abkoppeln, liegen die Verluste schnell im vierstelligen Euro-Bereich [1]. Das Risiko ist nicht zu unterschätzen.

Blanke Theorie

Ein wenig Theorie zu TCP ist nötig, um die Schwachstellen zu verstehen. Definiert ist das Protokoll im RFC 793 [2] aus dem Jahr 1981. Jedes TCP-Segment beginnt mit den Header, der neben dem Quell- und Ziel-Port (jeweils 16 Bit, Wertebereich 0 bis 65535) weitere wichtige Parameter enthält, etwa die Sequenz- und die Bestätigungsnummer (Sequence Number und Acknowledgement Number, beide 32 Bit, Wertebereich 0 bis 4294967295). Hinzu kommen Steuer-Flags (SYN, ACK, PSH, URG, RST und FIN) sowie die Größe des so genannten Empfangsfensters (Receive Window). Letzteres ist für den beschriebenen Angriff entscheidend (Abbildung 1).

Als eindeutiges Kennzeichen für eine geöffnete Verbindung dient die Vierergruppe (Quadrupel) aus Quell-IP und -Port und Ziel-IP und -Port. Die Sequenznummer bestimmt Byte-genau die Position des Segments im Datenstrom der Verbindung. Jeder, der das Quadrupel kennt und eine gültige Sequenznummer errät, hat alle Informationen parat, um sich in eine bestehende Verbindung einzuklinken. Egal wo sich der Angreifer befindet, er muss nur ein Paket fälschen und auf die Reise schicken.

Glücksspiel

Für die Sequenznummer stehen im Prinzip 232 Möglichkeiten zur Wahl. Die Chance, die richtige Zahl zu erraten und rechtzeitig das damit generierte Paket in die Verbindung einzuschleusen, ist bei dieser einfachen Rechnung sehr klein. Das gilt aber nur, wenn Sender und Empfänger ihre initialen Sequenznummern (ISN) beim Aufbau der TCP-Verbindung (Drei-Wege-Handshake) rein zufällig wählen. Im Verlauf der Verbindung erhöhen sie die Sequenznummer für jedes übertragene Byte um 1.

Während der Zielport meist durch die Anwendung und deren Dienst vorgegeben ist, kann der Quellport Werte zwischen 0 und 65535 annehmen. Dass die ersten 1024 Ports unter Unix nur privilegierten Prozessen zur Verfügung stehen, ist für die Schätzung unwichtig. Man ging lange Zeit einfach davon aus, dass ein Angreifer 232 Sequenznummern multipliziert mit 216 Möglichkeiten für den Quellport ausprobieren müsste, um eine TCP-Verbindung erfolgreich aus der Ferne anzugreifen, ohne die Übertragung zu belauschen. Leider wählen die meisten Betriebssysteme den Quellport nicht zufällig, doch dazu später.

Abbildung 1: Am Anfang jedes TCP-Segments steht dieser Header, dahinter folgen die Nutzdaten. Die Portnummern bezeichnen (zusammen mit den beteiligten IP-Adressen) die Verbindung, die Sequenznummer lokalisiert das Paket innerhalb des Datenstroms.

Abbildung 1: Am Anfang jedes TCP-Segments steht dieser Header, dahinter folgen die Nutzdaten. Die Portnummern bezeichnen (zusammen mit den beteiligten IP-Adressen) die Verbindung, die Sequenznummer lokalisiert das Paket innerhalb des Datenstroms.

Der dickste Rechenfehler folgt aus dem Fenstermechanismus (Windowing). Abbildung 2 zeigt die Funktion des Empfangsfensters. Im Internet können sich Pakete gegenseitig überholen. Durch das Receive Window gelingt es dem Empfänger, die einzelnen Segmente einzusammeln, in die richtige Reihenfolge zu bringen und am Stück zu bestätigen.

Das Glossar von RFC 793 erklärt den Fenstermechanismus frei übersetzt wie folgt: Das Receive Window ist der Bereich an Sequenznummern, die die lokale TCP-Instanz zu empfangen bereit ist. Das lokale TCP akzeptiert jedes Segment, dessen Sequenznummer mindestens der nächsten erwarteten Sequenznummer (RCV.NXT) entspricht, aber kleiner ist als RCV.NXT plus Fenstergröße (RCV.WND). Segmente mit einer Sequenznummer jenseits dieses Bereichs hält TCP für Duplikate und verwirft sie.

Fenster dicht

Wenn die Sequenznummer eines Pakets im Empfangsfenster liegt (der mittlere Bereich in Abbildung 2), dann akzeptiert TCP dieses Paket und verarbeitet es. Dadurch verkleinert sich die Anzahl der Rateversuche für den Angreifer erheblich; bei den Sequenznummern schrumpft sie von 232 auf 232/Fenstergröße. Je nach Betriebssystem liegt die Fenstergröße bei einem Wert von 65535 Bytes (Windows XP Professional mit SP2) und 5840 Bytes (Linux-Kernel 2.4 und 2.6), weitere Werte stehen in Tabelle 1. Sie schwankt zudem je nach Applikation. Während Cisco Telnet zum Beispiel eine Größe von 4192 Bytes verwendet, liegt die Fenstergröße von Cisco BGP bei einem Wert von 16384 Bytes.

In jedem Fall verringert das Empfangsfenster die Zahl der zu durchsuchenden Sequenznummern. Bei einem Windows-XP-System reduziert sie sich auf gerade einmal 65000. Das heißt, dass ein Saboteur lediglich 65000 Angriffspakete generieren muss, um ein gültiges RST-Paket einzuschleusen und damit eine Verbindung abzuschießen. Eine erschreckend kleine Zahl. Gute Intrusion-Detection-Systeme (IDS) schlagen zwar aufgrund der vielen RST-Pakete Alarm, Netze ohne dieses Feature werden aber bei einer hohen Netzlast den zusätzlichen Traffic nicht bemerken.

Es kommt noch schlimmer, wenn einer der Verbindungspartner Window Scaling benutzt. Diese TCP-Erweiterung (RFC 1323, [3]) steigert die Chance, innerhalb kurzer Zeit eine passende Sequenznummer zu finden.

Window Scaling ist für Verbindungen gedacht, die wegen ihrer hohen Bandbreite oder ihrer hohen Latenzzeit mit den Standard-Fenstergrößen nicht auskommen. Damit jeder Absender ohne Unterbrechung senden kann, ohne unnötig auf Bestätigungen zu warten, erhöht dieses Verfahren die Größe des Empfangsfensters um bis zu 14 Bit (bei Microsoft Windows). Das entspricht dem Faktor 16384. Nur wenn keiner der beiden Verbindungspartner dieses Feature benutzt, bleibt das Empfangsfensters durch RFC 793 auf einen Wert von 65535 Bytes begrenzt.

Abbildung 2: Die Sequenznummer eines eintreffenden TCP-Segments muss innerhalb des Empfangsfensters liegen, damit der Protokoll-Stack des Zielrechners das Paket als Teil der Verbindung erkennt.

Abbildung 2: Die Sequenznummer eines eintreffenden TCP-Segments muss innerhalb des Empfangsfensters liegen, damit der Protokoll-Stack des Zielrechners das Paket als Teil der Verbindung erkennt.

Tabelle 1: Initiale
Fenstergröße

 

Betriebssystem

Window Size

Linux-Kernel 2.4

5840 Byte

Linux-Kernel 2.6

5840 Byte

OpenBSD 3.6

16384 Byte

Windows 2000 SP1, SP2

17520 Byte

Windows 2000 SP3, SP4

65535 Byte

Windows 2000 MS05-019

17520 Byte

Windows XP Professional, SP2

65535 Byte

Unbekannter Quellport

Bleibt die Hürde für den Angreifer, das Quadrupel aus Quell- und Ziel-IP-Adresse und Quell- und Zielport zu erfahren. Die IP-Adressen stellen kein Problem dar: Der Angreifer weiß, wen er attackieren will. Gleiches gilt für den Zielport. Etwas schwerer hat er es beim Quellport, der theoretisch im Bereich zwischen 0 und 65535 liegt. In der Praxis reduziert sich der Wertebereich. Ports unterhalb von 1024 und jenseits einer Betriebssystem- abhängigen Grenze bleiben für spezielle Aufgaben reserviert.

Ein Linux-System (Kernel 2.4 und 2.6) mit mindestens 128 MByte Hauptspeicher verwendet Quellports zwischen 32768 und 61000 (bei weniger Speicher reduzieren sich diese Werte). Die Ports über 61000 benutzt der Kernel üblicherweise für Masquerading. Diese Werte sind in »/proc/sys/net/ipv4/ip_local_range« nachzulesen und mit Sysctl zu verändern, zum Beispiel »sysctl -w net.ipv4.ip_local_range=”32768 61000″«.

Raten nicht nötig

Die übrig bleibenden 28232 Möglichkeiten sind – sehr zur Freude von Angreifern – keineswegs zufällig verteilt, der Kernel vergibt sie nach einem bestimmten Muster. Das ist eine der wichtigen Erkenntnisse aus der Untersuchung von Paul Watson [4]. Es fällt Angreifern leicht, die Quellports vorherzusagen. Nur wenige Ausnahmen wie OpenBSD geben sich Mühe, die Portnummern nach Möglichkeit zufällig zu vergeben. Windows XP beginnt zum Beispiel mit Quellport 1050 bei der ersten Verbindung und erhöht diesen um 1 für jede weitere Verbindung. Linux (hier Fedora Core 3 mit Kernel 2.6.9) beginnt bei 32768 und erhöht ebenfalls um jeweils 1.

In Abbildung 3a ist ein Linux-System mit Kernel 2.6 zu sehen (Ports 32771 bis 32777). Im Vergleich dazu zeigt Abbildung 3b ein OpenBSD 3.6 mit zufällig gewählten Quellports. Cisco-Systeme erhöhen den Port bei jeder neuen Verbindung um den Wert 512 – sicherer ist dies Verfahren aber auch nicht.

Wichtige Begriffe

Acknowledgement Number: Dieser 32 Bit große Teil des TCP-Segmentheaders gibt die Sequenznummer an, die der Sender des Datensegments im TCP-Segmentheader des nächsten IP-Datagramms erwartet.

BGP: Das Border Gateway Protocol (sinngemäß: Grenzknotenprotokoll) beschreibt, wie sich Router gegenseitig über die Verfügbarkeit von Verbindungswegen informieren. Die Stärke des BGP-Protokolls liegt darin, verschiedene optionale Routing-Pfade in einer einzigen Routing-Tabelle zu vereinen.

Control-Bits: Flags im TCP-Segmentheader. Es gibt sechs Steuer-Bits:

  • SYN: Synchronisationsanforderung am Anfang einer
    Verbindung.
  • ACK: Der Absender bestätigt, dass er alle Pakete empfangen
    hat, deren Sequenznummer kleiner als der in der Acknowledgement
    Number angegebene Wert war.
  • FIN: Alle Daten gesendet (Finish; reguläres Ende einer
    Verbindung).
  • RST: Abbruch/Zurücksetzen der Verbindung (Reset).
  • PSH: Ein Push zeigt dem TCP-Stack an, dass er alle Puffer
    leeren und die noch ausstehenden Daten sofort senden oder an die
    zugehörige Applikation weitergeben soll.
  • URG: Ist das URG-Flag gesetzt, zeigt der Inhalt des
    Urgent-Felds im Header auf Daten, die der Empfänger bevorzugt
    (vor allen anderen) behandeln soll.

ICMP: Das Internet Control Message Protocol (definiert in RFC 792) wird hauptsächlich für die Fehlersuche und für Informationsmeldungen verwendet.

Looking Glass: Über diese Dienste lässt sich feststellen, ob und wie gut ein Server erreichbar ist [6]. Die Daten stammen von den beteiligten BGP-Routern und liefern eine klare Aussage zur Verbindungsqualität. Ping und Traceroute können zusätzliche Informationen über die dazwischen liegenden Systeme ermitteln.

MD5-Signatur: MD5 berechnet eine eindeutige Prüfsumme (Hashwert) über eine beliebig große Datenmenge. Wird bei der Berechnung zusätzlich ein Passwort berücksichtigt, dient MD5 als Signatur (Keyed Hash).

Sequence Number: Dieser 32 Bit große Teil des TCP-Segmentheaders gibt die Nummer des ersten Oktetts (Bytes) im Datenteil an. Mit ihrer Hilfe kontrolliert der Empfänger die Reihenfolge und Gültigkeit der Pakete. Das schützt ihn vor mehrfach gesendeten Paketen (Replay) oder eingeschleusten Paketen (Injection). Der Schutz ist allerdings auf zufällige Fehler ausgelegt; gegen absichtliche Manipulation hilft er nur schwach.

TCP: Das Transmission Control Protocol (definiert in RFC 793) steuert den Datentransfer zwischen Absender und Empfänger. Es arbeitet im Gegensatz zum User Datagram Protocol (UDP, definiert in RFC 768) verbindungsorientiert und sorgt dafür, dass der Empfänger alle ausgelieferten Daten unversehrt und in der korrekten Reihenfolge erhält.

Window Size: Dieser 16 Bit große Teil des TCP-Segmentheaders gibt die Anzahl der Datenoktetts (Bytes) an, die der Sender des TCP-Segments noch als gültig akzeptieren wird.

Window Scaling: Verfahren, um die Performance von Verbindungen mit hoher Bandbreite oder hoher Latenzzeit zu optimieren. Bei Window Scaling wird die Größe des Empfangsfensters (Window Size) erhöht. Damit verarbeitet eine Instanz auch verspätet eintreffende Pakte ohne erneutes Versenden und sendet mehr Daten, ohne auf Bestätigungen zu warten.

Abbildung 3a: Das Kommando »netstat -nt« listet die TCP-Verbindungen des lokalen Rechners. Die Quellport-Nummern folgen einem einfachen Schema: Der Kernel erhöht die Nummer für jede Verbindung um 1.

Abbildung 3a: Das Kommando »netstat -nt« listet die TCP-Verbindungen des lokalen Rechners. Die Quellport-Nummern folgen einem einfachen Schema: Der Kernel erhöht die Nummer für jede Verbindung um 1.

Abbildung 3b: OpenBSD vermiest Angreifern nach Kräften ihr Handwerk. Unter anderem gibt es jeder Verbindung einen zufälligen Quellport - der Saboteur muss immer raten und kann die Nummer nicht berechnen.

Abbildung 3b: OpenBSD vermiest Angreifern nach Kräften ihr Handwerk. Unter anderem gibt es jeder Verbindung einen zufälligen Quellport – der Saboteur muss immer raten und kann die Nummer nicht berechnen.

Ein Angreifer muss den Quellport nicht erraten, wenn er weiß, mit welcher Nummer sein Opfer derzeit arbeitet. Es genügt in der Regel, beim Startwert zu beginnen und vielleicht 50 Ports zu versuchen. Das verwendete Betriebssystem sowie die Netzkonfiguration finden Neugierige mit Fingerprinting-Techniken schnell heraus. Eine echte Hürde sind die vorhersagbaren Quellports also nicht.

Angriffstechniken

Viele Angriffsvarianten auf TCP-Verbindungen profitieren von den bisher beschriebenen Schwächen. Bei einer Angriffstechnik schleust ein Saboteur RST-Steuerbits ein (Reset). Laut RFC 793 teilt dieses Flag dem Empfänger mit, dass er ohne weitere Interaktionen die Verbindung löschen soll. Der Empfänger entscheidet anhand der Sequenznummer und eventuell der Bestätigungsnummer, ob er dem Wunsch folgt oder das Reset-Kommando ignoriert. Auf keinen Fall darf er mit einem eigenen RST-Kommando antworten.

Wichtig an der Spezifikation ist, dass der Empfänger die Gültigkeit des RST immer anhand der Gültigkeit der Sequenznummer überprüfen muss. Nur wenn sie innerhalb des Empfangsfensters liegt, beendet er die Verbindung. Theoretisch könnte er zusätzlich die Bestätigungsnummer benutzen, er muss es aber nicht. Der Sicherheitsexperte Paul Watson (siehe Kasten “Historie”) hat recht viele TCP-Stacks daraufhin untersucht und festgestellt, dass die meisten die Bestätigungsnummer in diesem Fall ignorieren [4].

Ein im Laufe der Verbindung empfangenes RST-Paket, das in das erlaubte Fenster der Verbindung passt, führt damit unweigerlich zu ihrem Abbruch. Gerade länger andauernde Verbindungen, zum Beispiel die BGP-Verbindungen zwischen Routern, sind für Reset-Angriffe besonders anfällig. Zum einen ist die Zeit, in der Angreifer ein Paket einschleusen können, hinreichend lang, zum anderen ist auch der entstehende Schaden durch den DoS hoch. Die Router müssen ihre Neighbour-Tabelle neu konfigurieren. In einer realen Umgebung kann das einige Minuten dauern.

Synchron sterben

Weniger offensichtlich ist, dass sich auch das SYN-Flag zum Abschießen einer Verbindung eignet. RFC 793 definiert, dass bei gesetztem SYN am Anfang einer Verbindung das Sequence-Number-Feld den Startwert für die künftig verwendeten Sequenznummern enthält. Sollte ein SYN-Paket später im Verlauf einer Verbindung eintreffen, erklärt RFC 793 dies zu einem Fehler. Die Folge: Der Empfänger muss die Verbindung unverzüglich mit einem Reset-Paket abbrechen.

Mit diesem Verhalten vermeidet TCP doppelt initiierte Verbindungen, etwa nach einem Reboot des Verbindungspartners. Das Senden eines RST- oder SYN-Flags in einem IP-Datagramm mit gültiger Sequenznummer hat also den gleichen Effekt: Es beendet die Verbindung. Im Gegensatz zu einem RST-Paket antwortet der Host jedoch auf ein SYN-Paket, und zwar mit einem RST-Paket. Der Fachausdruck für dieses Verhalten: Der Empfänger reflektiert das Paket.

Damit gelingt ein weiterer DoS: Der Angreifer sorgt dafür, dass sein Opfer die komplette Bandbreite seiner ausgehenden Leitung erschöpft. Besonders bei ADSL-Leitungen lohnt diese Technik. Das Opfer empfängt Daten mit viel höherer Geschwindigkeit, als es sendet.

Während beim RST- und SYN-Angriff der Datenbereich des IP-Datagramms leer bleibt, schleust eine dritte Technik Daten in eine bestehende Verbindung ein. Das können willkürliche Daten sein, die die Verbindung korrumpieren, oder der Angreifer fälscht die Daten bewusst und schleust damit Fehler ein. Das Opfer bemerkt von der Manipulation möglicherweise nichts.

Praxis

Um seine Theorien [4] in der Praxis zu erproben, entwickelte Paul Watson das Tool »reset_tcp.c« und veröffentlichte es im Mai 2004 [13]. Dabei stellte er fest: Selbst eine einfache DSL-Verbindung reicht aus, um bei einer Window Size von 65535 Bytes und 50 zu untersuchenden Quellports innerhalb von elf Minuten eine Sequenznummer zu erraten, die eine Verbindung abbrechen lässt. Bei einer Größe des Empfangsfensters von nur noch 16384 Bytes steigt der Aufwand auf 45 Minuten.

Das Programm braucht die von Mike D. Schiffman entwickelte Libnet Packet Construction Library [14]. Bereits vor dem Übersetzten sind in den Quellen die MAC-Adressen des eigenen und des Ziel-Interface einzutragen. Letzteres wird meist das Default-Gateway sein oder das Interface des anzugreifenden Rechners, falls der sich im lokalen Netz befindet. Beim Aufruf erwartet das Programm weitere Parameter: »reset_tcp Interface Quell-IP Quellport Ziel-IP Zielport Fenstergröße«. Als Interface wählt man die Netzwerkkarte, auf der die RST-Pakete den Rechner des Angreifers verlassen werden.

Beim ersten Praxistest soll das Tool eine SSH-Verbindung zwischen zwei Linux-Rechnern trennen (Abbildung 4). Beide sind über T-DSL 1000 der Telekom ans Internet angebunden (Upstream: 128 KBit/s). In diesem einfachen Test soll der Angreifer den Quellport bereits kennen. Die Größe eines RST-Pakets beträgt 40 Byte (für IP- und TCP-Header), umgerechnet 320 Bit.

Für beide Richtungen betrage die Fenstergröße 5840. Dank der Theorie lässt sich berechnen, wie lange es höchstens dauert, bis die Verbindung zusammenbricht: Maximalwert der Sequenznummer geteilt durch Fenstergröße, multipliziert mit der Größe eines Pakets geteilt durch die Übertragungsrate. Mit konkreten Werten: 4294967296 / 5840 * 320 Bit / 128000 Bit/s. Das ergibt knapp 1840 Sekunden, also 30 Minuten und 40 Sekunden.

Abbildung 4: Ethereal beobachtet einen TCP-Reset-Angriff auf eine SSH-Verbindung. Der Saboteur sendet viele TCP-Segmente mit wachsender Sequenznummer (oberes Fenster, gegen Ende der Zeilen: »Seq=...«). In der Detailansicht (Mitte) ist zu erkennen, dass das Reset-Flag gesetzt ist.

Abbildung 4: Ethereal beobachtet einen TCP-Reset-Angriff auf eine SSH-Verbindung. Der Saboteur sendet viele TCP-Segmente mit wachsender Sequenznummer (oberes Fenster, gegen Ende der Zeilen: »Seq=…«). In der Detailansicht (Mitte) ist zu erkennen, dass das Reset-Flag gesetzt ist.

Haben alle Versuche dieselbe Trefferwahrscheinlichkeit, dann ist der Angreifer im Mittel nach der halben Zeit am Ziel, also nach 15 Minuten und 20 Sekunden. Die Messungen der Autoren bestätigen diese Berechnung: Bei 20 Messungen ermittelten sie einen Mittelwert von 932 Sekunden (15 Minuten und 32 Sekunden). Müssten sie (bei einem Rechner mit wenigen Netzwerkverbindungen) 50 Quellports durchprobieren, würde die Angriffszeit auf etwa 13 Stunden steigen. Selbst für langlebige SSH-Verbindungen ist das ein sehr aufwändiger Prozess.

Variable Fenster

Die meisten Betriebssysteme passen die Window Size im Laufe der Verbindung dem Datenaufkommen an. So erhöht Linux die Fenstergröße bei einer SSH-Verbindung, die lediglich die Ausgaben eines »top«-Kommandos übermittelt, bereits auf Werte über 16000. Weiß der Angreifer, dass sein Opfer über die Verbindung größere Datenmengen überträgt, kann er problemlos eine größere Window Size nutzen. Für eine SSH-Verbindung, über die der Benutzer »top« aufruft, haben die Autoren nachgemessen: Bei einer Fenstergröße von 16000 und bekanntem Quellport gelang der Angriff im Mittel binnen 5 Minuten und 45 Sekunden.

Fenstergröße
ändern

Die Größe des TCP-Empfangsfensters ist variabel. Der Admin kann bei den meisten Betriebssystemen regulierend eingreifen und Default- sowie Maximalwerte ändern.

Linux-Kernel 2.4 und 2.6 mit IPv4: Anpassung der Werte von »/proc/sys/net/ipv4/tcp_ rmem« und »/proc/sys/net/ipv4/wmem« oder Eintrag der Werte »tcp_rmem« und »tcp_wmem« in der Datei »/etc/sysctl.conf« mit anschließendem Aufruf von »sysclt -p«. Eine sehr gute Dokumentation liefert [19].

Windows 2000 und XP: Anpassen der Werte »GlobalMaxTcpWindowSize« (Typ REG_DWORD) und »TcpWindowSize« (Typ REG_DWORD) in dem Registry-Eintrag »HKEY_LOCAL_MACHINE SYSTEMCurrentControlSetServicesTcpipParameters«. Eine sehr gute Dokumentation findet sich unter [18].

Cisco IOS: Hier lässt sich die Fenstergröße im so genannten Enable Mode durch den Befehl »ip tcp window-size Fenstergröße« einstellen.

Sun Solaris: Bei Solaris-Systemen erzielt das NDD-Kommando den gewünschten Effekt: »ndd -set /dev/tcp tcp_xmit_hiwat Fenstergröße« und »ndd -set /dev/tcp tcp_recv_hiwat Fenstergröße«.

Auch Watsons Beispiel einer BGP-Verbindung war Ausgangspunkt für eigene Messungen: Ein Linux-Rechner (Kernel 2.4, initiale Fenstergröße 5840) kommuniziert per BGP mit einer Cisco-Gegenstelle (initiale Window Size 16384). Die Fenstergröße ändert sich erwartungsgemäß beim Übertragen von Daten. Zu Beginn einer Verbindung übermittelt BGP recht große Datenmengen, im gewählten Setup stieg die Window Size in beiden Richtungen nach wenigen Minuten auf 16616 und blieb dann konstant.

Der theoretische Mittelwert für einen erfolgreichen Angriff ist: 4294967296 / 16616 * 320 Bit / 128000 Bit/s / 2 = 5 Minuten und 23 Sekunden. Der gemessene Mittelwert 5 Minuten und 39 Sekunden bestätigt dieses Ergebnis. BGP-Verbindungen bleiben üblicherweise aber wochen- oder gar monatelang bestehen, ihr Aufbau dauert meist über eine Minute und BGP-Router öffnen von sich aus nur sehr wenige Netzwerkverbindungen. Aus diesen Gründen hat ein Angreifer leichtes Spiel – er muss nur wenige Quellports durchprobieren und kann sich viel Zeit nehmen.

Streusalz

Wegen des hohen Risikos für das Opfer und der geringen Gefahr für den Angreifer ist es wichtig, sich rechtzeitig auf Attacken vorzubereiten. Es gibt einige Maßnahmen, die die Auswirkungen der geschilderten Probleme deutlich mildern. Generell gilt: Möglichst wenig Informationen über die eigene Anbindung und die Konfiguration des eigenen Netzes nach außen geben. Übertrieben informativ sind etwa Looking Glasses (BGP; siehe Kasten “Wichtige Begriffe” und [6]) sowie manche DNS-Einträge.

Bei vielen Betriebssystemen ist die Größe des Empfangsfensters einstellbar (siehe Kasten “Fenstergröße ändern”); ein kleiner Wert erschwert die Sabotage. Auf Window Scaling sollte man verzichten. In der Folge passen weniger Sequenznummern in das Empfangsfenster, der Angreifer muss genauer treffen. Das kostet ihn mehr Zeit und Bandbreite.

Performance-Falle

Allerdings hat dieses Tuning seine Grenzen: Bei zu niedrigen Werten leidet die Performance. TCP arbeitet deutlich langsamer, das Protokoll wartet zu häufig auf Empfangsbestätigungen statt weiterzusenden. Zudem muss es mehr Bestätigungen (ACKs) verschicken, der Overhead steigt also an. Ein extremes Beispiel: Bei der Fenstergröße 10 ist für jeweils 10 Byte Daten ein ACK-Paket von mindestens 40 Byte notwendig (20 Byte IP-Header, 20 Byte TCP-Header).

Gezielter gegen Reset-Attacken wirken Filterregeln auf den Border-Gateways. Router sollten nur ein- und ausgehenden Traffic akzeptieren, dessen IP-Quelladresse zu der Routerseite passt, von der das Paket stammt. Das grenzt IP-Spoofing-Angriffe ein, eigentlich eine Pflichtaufgabe für jeden Router. Es schützt das interne Netz auch vor gefälschten Paketen von außen, die vorgeben von innen zu stammen, sowie den Rest des Internet vor Spoofern, die im eigenen Netz sitzen. Vorsichtige Admins ergänzen weitere Filterregeln, die nur BGP-Verkehr von und zu bekannten Routern akzeptieren. Damit ist ein Angriff auf BGP-Verbindungen kaum noch möglich.

Bereits seit 1998 gibt es einen weiteren Schutz: RFC 2385 beschreibt MD5-basierte Signaturen für TCP-Verbindungen [7]. Dieses Verfahren erzeugt Hashes von einem Passwort zusammen mit allen wesentlichen Feldern des TCP-Headers. Damit erkennt der Empfänger Fälschungen. Die Passwörter dürfen nicht trivial sein, da Passwort-Cracker wie »bgpcrack« [9] sonst per Wörterbuchattacke die Signatur knacken. Eine gute Übersicht zu dieser und anderen BGP-Schwachstellen sowie weitere Lösungsvorschläge sind in [8] und [10] zu finden.

Abbildung 5a: Ein klassischer TCP-Stack nach RFC 793 bricht seine Verbindung sofort ab, wenn er ein zur Verbindung passendes RST-Paket empfängt. Es genügt, wenn die Sequenznummer im Empfangsfenster liegt, sie muss nicht exakt stimmen. Angriffe sind dadurch unnötig einfach.

Abbildung 5a: Ein klassischer TCP-Stack nach RFC 793 bricht seine Verbindung sofort ab, wenn er ein zur Verbindung passendes RST-Paket empfängt. Es genügt, wenn die Sequenznummer im Empfangsfenster liegt, sie muss nicht exakt stimmen. Angriffe sind dadurch unnötig einfach.

Abbildung 5b: Der nach [11] modifizierte Stack verlangt, dass die RST-Sequenznummer exakt stimmt. Liegt sie nur innerhalb des Empfangsfenster, reagiert er mit einem ACK. Ein legitimer Absender erkennt, dass zwischenzeitlich Pakete verloren gingen und das Gegenüber folglich sein RST ignorierte.

Abbildung 5b: Der nach [11] modifizierte Stack verlangt, dass die RST-Sequenznummer exakt stimmt. Liegt sie nur innerhalb des Empfangsfenster, reagiert er mit einem ACK. Ein legitimer Absender erkennt, dass zwischenzeitlich Pakete verloren gingen und das Gegenüber folglich sein RST ignorierte.

Vorsichtige Antworten

Im April 2004 veröffentlichte die IETF einen Internet-Draft [11], der Änderungen im TCP-Antwortverhalten vorschlägt. Eine TCP-Instanz soll auf eintreffende RST-Flags nur dann sofort reagieren, wenn deren Sequenznummer exakt mit der erwarteten übereinstimmt. Liegt sie lediglich innerhalb des Empfangsfensters, antwortet die Instanz mit einem ACK-Flag und verwirft das Segment. Der Empfänger des ACK kann mit einem zweiten RST reagieren (Abbildung 5b). Die Idee: Ein Fälscher wird das ACK-Paket nicht sehen und daher keine bessere Chance als beim ersten Versuch haben. Stammt der erste RST vom echten Absender, kann er auf den ACK reagieren und die Verbindung im zweiten Anlauf korrekt beenden.

Das neue Verhalten führt jedoch zu einer neuen Verwundbarkeit: Bei so genannten ACK-Kriegen (ACK War) überschwemmt der Angreifer sein Ziel mit RST-Paketen. Antwortet das Opfer auf jeden RST, dann belastet es seine Leitung auch in der Gegenrichtung. Eine ADSL-Anbindung ist damit schnell blockiert. Um das zu vermeiden, sollte jeder Host innerhalb von fünf Sekunden maximal zehn RST-Pakete mit je einem ACK beantworten.

Beim Empfang eines SYN-Flag empfiehlt der Draft immer mit einem ACK die Echtheit zu überprüfen. Alle Vorschläge sind mit dem ursprünglichen Verhalten nach RFC 793 kompatibel. Der Draft nutzt die TCP-Features, um dessen Schwachstellen zu bekämpfen. Die beschriebene Gefahr eines DoS-Angriffs durch Sättigung der Leitung ist trotz aller Verbesserungen aber nicht zu bannen.

Vorbeugen ist gefragt

Für Linux gibt es noch eine Schutztechnik: Das GR-Security-Patch [12] sorgt unter anderem dafür, dass Kernel 2.4 und 2.6 die Quellports zufällig vergeben. Dieses Feature stammt – wie viele andere aus diesem Patch – von OpenBSD. Bei Messungen bewährte es sich: Es vereitelte jeden Versuch, eine Verbindung aus der Ferne abzubrechen.

Bei TCP-RST- und den verwandten TCP-SYN-Attacken handelt es sich um eine nicht zu unterschätzende Gefahr. Passende Skripte und Tools für Angreifer sind frei erhältlich und es genügt eine simple DSL-Anbindung, um langlebige Verbindungen erfolgreich anzugreifen. Theo de Raadt, Maintainer des OpenBSD-Projekts, sagte einmal zu diesem Angriffstyp: “Viele Leute sagen, dass das kein Problem darstellt. Aber ich bin mir sicher, dass eines Tages ein Wurm diese Schwäche nutzen wird.” Nur wer rechtzeitig die im Artikel vorgestellten Schutzmöglichkeiten umsetzt, darf dem gelassen entgegensehen. (fjl)

Historie

1981: Im Request for Comment (RFC) 793 wird das Transmission Control Protocol (TCP) spezifiziert [2].

1985: Bob Morris weist auf Schwachstellen im TCP hin [15].

1994: Erste bekannt gewordene Manipulation, die eine TCP-Schwachstelle ausnutzt. Hacker-Legende Kevin Mitnick verwendet seine so genannte Christmas Day Attack für einen Angriff auf das Netz des Sicherheitsexperten Tsutomu Shimomura [20].

1995: Paul Watson veröffentlicht im Usenet ein Posting zu den Schwachstellen von TCP, das große Aufmerksamkeit auf sich zieht. Die Bereitschaft steigt, sich mit dieser Thematik zu beschäftigen. Es folgen zahlreiche Untersuchungen, vor allem zu den Generatoren für Sequenznummern.

1995: Laurent Joncheray präsentiert auf der Usenix-Konferenz sein Paper “Simple Active Attack against TCP” [16].

2001: Das Cert beschreibt eine Schwachstelle in mehreren TCP/IP-Sequenznummern-Generatoren und weist auf die Problematik der Window Size hin [17].

2003: Paul Watson zeigt, dass Angriffe selbst mit einer einfachen DSL-Anbindung sehr wirkungsvoll auszuführen sind.

2004: Die IETF (Internet Engineering Task Force) veröffentlicht die erste Version des Internet-Draft “Improving TCP\’s Robustness to Blind In-Window Attacks” [11].

Infos

[1] Computer Security Institute: [http://www.gocsi.com]

[2] RFC 793, “Transmission Control Protocol”: [http://rfc.net/rfc793.html]

[3] RFC 1323, “TCP Extensions for High Performance”: [http://rfc.net/rfc1323.html]

[4] Paul Watson, “Slipping in the Window: TCP Reset Attacks”: [http://www.osvdb.org/reference/SlippingInTheWindow_v1.0.ppt]

[5] Paul Watson, “TCP Reset Spoofing”: [http://www.osvdb.org/4030]

[6] IPv4 Looking Glass Sites: [http://www.bgp4.net/lg]

[7] RFC 2385, “Protection of BGP Sessions via the TCP MD5 Signature Option”: [http://rfc.net/rfc2385.html]

[8] Sean Convery und Matthew Franz, “BGP Vulnerability Testing: Separating Fact from FUD v1.1”: [http://www.blackhat.com/presentations/bh-usa-03/bh-us-03-convery-franz-v3.pdf]

[9] BGP-Crack: [http://cisco.com/security_services/ciag/tools/bgpcrack-2.1.tar.gz]

[10] Björn Griesbach, “Sicheres Routing mit S-BGP”: [http://www.net.informatik.tu-muenchen.de/teaching/WS03/security/final/12_sbgp.pdf]

[11] Internet-Draft, “Improving TCP\’s Robustness to Blind In-Window Attacks”: [http://ietfreport.isoc.org/idref/draft-ietf-tcpm-tcpsecure/]

[12] GR-Security: [http://www.grsecurity.net]

[13] TCP Connection Reset Remote Exploit: [http://www.frsirt.com/exploits/04232004.tcp-exploit.php]

[14] Libnet: [http://www.packetfactory.net/projects/libnet/]

[15] Robert T. Morris, “A Weakness in the 4.2 BSD Unix TCP/IP Software: [http://pdos.csail.mit.edu/~rtm/papers/117.pdf]

[16] Laurent Joncheray, “Simple Active Attack Against TCP”: [http://www.usenix.org/publications/library/proceedings/security95/full_papers/joncheray.ps]

[17] Cert Advisory CA-2001-09, “Statistical Weaknesses in TCP/IP Initial Sequence Numbers”: [http://www.cert.org/advisories/CA-2001-09.html]

[18] Dave MacDonald und Warren Barkley, “Microsoft Windows 2000 TCP/IP Implementation Details”: [http://www.microsoft.com/technet/itsolutions/network/deploy/depovg/tcpip2k.mspx]

[19] Oskar Andreasson, “Ipsysctl tutorial – Chapter 3, IPv4 variable reference”: [http://ipsysctl-tutorial.frozentux.net/chunkyhtml/tcpvariables.html]

[20] Cert Advisory CA-1995-01, “IP Spoofing Attacks and Hijacked Terminal Connections”: [http://www.cert.org/advisories/CA-1995-01.html]

Die Autoren


Wilhelm Dolle ist CISSP (Certified Information System Security Professional) und BSI-IT-Grundschutz-Auditor. Er verantwortet als Mitglied der Geschäftsleitung der Interactive Systems GmbH den Bereich Information Technology und IT-Security.


Christoph Wegener ist promovierter Physiker und Leiter des Bereichs Business Development bei der Gits AG. Außerdem ist er seit vielen Jahren freier Berater in den Bereichen Linux und IT-Sicherheit.

LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben