Ping of Death detailiert erklären

Kann jemand den klassischen PoD genau erklären? Mir geht es dabei nicht um die Manipulation der Fragmente, sondern darum wie genau die Pakete verarbeitet wurden.

Wie war die Reassemblierung in alten Systemen genau implementiert (z.B. Linux <2.0.23)? Wo genau trat der Fehler auf? Hatte der Fehler überhaupt irgendwas mit ICMP zu tun oder waren alle IP-Pakete betroffen? Kennt jemand die entsprechenden src-files, die man sich ansehen sollte?
Was läuft dort über (Speicherbereich oder Variable)? War über die Schwachstelle Codeinjection möglich?

Leider genügen meine Kenntnisse zur Betriebssystemarchitektur noch nicht um mir diese Fragen selbst zu beantworten.
 
Das Problem war eine 16bit Integer-Variable. Durch geschicktes Fragmentieren und Manipulieren des Offsets des letzten Fragmentes konnte man erreichen, dass auf dem Zielsystem, auf dem die Fragmente wieder zusammengesetzt werden, der Wert dieser Variable größer als 65536 wird und der Speicher somit überläuft.
Dabei war nicht nur ICMP davon betroffen, sondern es war ein generelles Problem in der IP-Implementierung.

Eine gute Erklärung findest du hier:
http://insecure.org/sploits/ping-o-death.html

Btw, eine Variable ist quasi ein Speicherbereich. :)
 
Zuletzt bearbeitet von einem Moderator:
Den Artikel von Insecure kannte ich schon. Der hat leider nicht weitergeholfen. Der Tipp, dass die gesamte IP-implementierung betroffen war hat aber geholfen.
Inzwischen ist es mir gelungen den Code zu finden. Der Bug befindet sich in in ip_fragment.c. Den fehlerhaften Code gibt es auf http://stuff.mit.edu:8001/afs/net/user/tytso/linux/linux-2.0.23/net/ipv4/.

Ich hab jetzt selbst mal probiert das Problem zu analysieren bin aber noch nicht zu einem abschließenden Ergebnis gekommen.

ip_defrag() ist die Routine, welche die Fragmente zusammensetzt. Dort werden jedoch ausser den IP-Headerinformationen (die werden nur gelesen) keine 16-bit Variablen verwendet. Die Funktion baut zuerst die Fragmentliste zusammen und macht am Ende das Datagram draus, wenn die Liste vollständig ist.
Ich sehe durch pures draufschauen erstmal keinen Grund warum man keine größeren Fragmentlisten bauen kann. Meine aktuelle Vermutung ist, dass size_t in den alten Versionen nur 16 bit hat und demnach zu wenig Speicher fürs zusammenkleben reserviert wird (kann das jemand bestätigen?). Werde mich demnächst mal dransetzen und den Code nochmal mit Debugger analysieren.

Interessant ist übrigens auch der Fix für das Problem (http://lkml.indiana.edu/hypermail/linux/kernel/9610.2/0233.html). Dort wird direkt nach Eingang des Paketes auf offset+Fragmentgöße geprüft. Leider wird erst danach geprüft, ob das fragment mit vorherigen überlappt und ggf. das Offset wieder vergrößert. Somit war der PoD wohl auch nach dem Fix noch in abgewandelter Variante möglich.
 
Meine aktuelle Vermutung ist, dass size_t in den alten Versionen nur 16 bit hat und demnach zu wenig Speicher fürs zusammenkleben reserviert wird (kann das jemand bestätigen?).

Laut RFC 791 darf ein IP-Paket (inkl. Header) nicht größer als 65535 Bytes sein. Diese Größe ist vorgegeben, da im IP-Header für die Total Length nur 16 Bit reserviert sind und somit die größte Zahl, die darin gespeichert werden kann, 65535 ist.
Nun wird aber aufgrund der durch die MTU definierten Frame-Größe das IP-Paket in sogenannte IP-Fragmente aufgesplittet und beim Empfänger wieder zusammengesetzt. Damit die Fragmente wieder korrekt zusammengesetzt werden können, muss jedes Fragment Informationen bereitstellen, welchen Teil des ursprünglichen IP-Paket es enthält. Diese Informationen werden im IP-Header im 13 Bit langen Offset-Feld gespeichert. Es wird dabei in 8 Byte-Schritten das Offset des Fragmentes relativ zur Position im ursprünglichen Paket angegeben. Da das erste Offset mit 0 beginnt wäre also das maximale Offset ((2^13) - 1) * 8 = 65528 und somit wäre nur noch 7 Bytes für den Payload übrig, wenn man die die maximale Paketgröße von 65535 Bytes nicht überschreiten will.
Da nun die meisten IP-Implementierungen die Fragmente nicht direkt weiterverarbeiten, sondern erst zusammensetzen, muss beim Reassemblieren die aktuelle Paketgröße in einer Variablen gespeichert werden. Das ist oder war (ich hab keine Ahnung wie es momentan aussieht) eine 16bit Variable. Wenn nun ein Angreifer IP-Fragmente derartig manipuliert, dass das maximale Offset erreicht wird und er mehr als 7 Byte an Payload dranhängt, war bei dieser Variablen spätestens bei 65536 Schluss.

Da ich mir den ganzen Code nun nicht anschauen will, kann ich dir leider auch nicht sagen, wie die spezifische Variable genau heißt oder wo sie zu finden ist. Das müsstest du dann anhand der Beschreibung selber herausfinden. :)
 
Wenn nun ein Angreifer IP-Fragmente derartig manipuliert, dass das maximale Offset erreicht wird und er mehr als 7 Byte an Payload dranhängt, war bei dieser Variablen spätestens bei 65536 Schluss.

[x] true


Da ich mir den ganzen Code nun nicht anschauen will, kann ich dir leider auch nicht sagen, wie die spezifische Variable genau heißt oder wo sie zu finden ist. Das müsstest du dann anhand der Beschreibung selber herausfinden.

Das duerfte bei NT code auch schwer werden ;)


@ArnoNühm
PoD ist im Netz absolut erschoepfend erklaert worden.
 
@ArnoNühm
PoD ist im Netz absolut erschoepfend erklaert worden.

offensichtlich nicht. mir gelingt es jedenfalls nicht etwas zu finden, was genau beschreibt wie der fehler auftritt. klar gibt es 1000 dokumente, die idiotensicher erklären wie man oversized packets verschickt. ich suche aber eine erklärung an welcher stelle genau der fehler z.B. in linux 2.0.23 auftritt.
hab heut nochmal erneut ip_defrag() angesehen und bin inzwischen der meinung, dass überlange pakete dort noch korrekt verarbeitet werden. ich finde jedenfalls nichts was dagegenspricht. als resultat müsste dann nen skbuff rauskommen, der einen wegen überlauf viel zu kleinen length-wert im iphdr hat. ich finde aber noch nicht an welcher stelle dieser wert das system durcheinanderbringt.
 
Zurück
Oben