Updates sind wichtig!
Ein Fachartikel über „buffer overflow“.
Kenne Sie das nicht auch? Schon wieder ein Update, warum soll ich das durchführen, die Häufigkeit von Updates nervt, warum braucht mein Auto ein Update usw..
Bedauerlicherweise hörte ich letzte Woche erneut, dass sich ein Kunde nicht von seinem Windows 7 Rechner trennen will. Seine Argumente waren:
- eine Firewall ist vorhanden,
- einen Virenschutz ebenso,
- ihn greift sowieso keiner an,
- Windows 7 läuft zuverlässig.
Eines vorweg. Eine Firewall hilft gegen buffer overflow meist recht wenig und auch Virenscanner versagen in vielen Fällen. Darauf sollten sie sich also nicht verlassen.
Wenn Sie ein IPS verwenden, erwarten Sie auch hier keine Alarmmeldung. Ein Hintergrund ist, dass diese Systeme häufig fehlerhaft implementiert werden.
Buffer overflow – Überlauf
Die buffer overflow Methode ist eine sehr beliebte Vorgehensweise, um in Ihren Rechner einzudringen. In der Cybersecurity spricht man von einem Angriffsvektor.
Wie der Name (buffer overflow) schon verrät, werden reservierte Speicherbereiche in Ihrem Rechner geflutet und andere Speicherbereich werden überschrieben.
Stellen Sie sich ein Glas vor. Sie befüllen das Behältnis vollständig mit einer Flüssigkeit. Ein Bekannter erlaubt sich nun einen Scherz und füllt mehr Wasser ins Glas. Das Wasser läuft erst mal über den Rand des Glases und verteilt sich unkontrolliert am Boden. Sinngemäß wurde der Wasserspeicher (buffer) nun überflutet (overflow) und das Wasser kann sich außerhalb des Glases verteilen.
Nehmen wir das Beispiel und gehen auf den PC zurück.
- Um es anschaulich darzustellen, ein Beispiel:
Das ist eine Ursache, dass die Software, welche wir nutzen, mit hoher Sicherheit etliche Fehler hat.
Funktionsweise des buffer overflows
Der Speicherausbau
Der Kernelbereich:
Hier laufen betriebssystemnahe Programme und Software. Zum Beispiel Treiber von Maus und Drucker. Microsoft ist bemüht, dass Attacken abgewehrt werden, da man in diesem Bereich übergreifend agieren könnte. Hierzu hat der Hersteller u. a. Code Integrity (CI), Control Flow Guard (CFG) und Kernel Data Protection (CFG) eingeführt. Wir werden diese Mechanismen in einem anderen Beitrag erläutern. Diese Schnittstellen sind auch nicht immer fehlerfrei. In früheren Windowsversionen gab es einen ungeschützten „direct memory Zugriff“. Man konnte Daten direkt von anderen Programmen auslesen (z. B. über die Grafikkarte).
Der Stackbereich
In diesem Bereich tummeln sich beispielweise dynamische Programmmodule (DLL), welche von Microsoft, vom Programmierer oder Softwarelieferanten kommen und vom Programm benötigt werden. Hier lagert das Programm aber auch seine Funktionen aus.
Der Heapbereich
Auch ein Programm hat dynamische Variablen, global definierte Speicherbereiche etc.. Diese werden in der Regel im Heap abgelegt (siehe auch Quelle 3). Mit Fehlern in Heap-Segment beschäftigen wir uns in einem anderen Beitrag.
Der Code und Textbereich
Wenn ein Programm startet, denn belegt es einen gewissen Speicherplatz. Alle statischen Funktionen, Instruktionen und Konstanten belegen einen fest definierten Speicher. Wenn Sie mehr wissen wollen, folgen Sie bitte unseren Quellen und es gibt Programme, welche die Speicherbereiche sehr gut und detailliert darstellen. Wir werden uns nachfolgend mit dem Stackbereich näher beschäftigen, um das Thema buffer overflow zu verstehen.
Speicheraufbau eines 32 Bit Programms
Grundlegender Aufbau einer 32 Bit Applikation.
Zu sehen sind die Bereiche:
- Stack
- Heap
- Code und Text
in vereinfachter Form.
Man sieht, dass Stack und Head dynamisch angelegt sind und sich aufeinander zubewegen.
Im Stackbereich werden Funktionen der Applikation abgelegt.
Die Funktionsaufruf und besonders die Rücksprungadresse können verändert werden, wenn buffer – overflow funktioniert.
Ein einfaches Beispiel
Wir haben zwei Variablen. Die erste Variable nennen wir „Vorname“ und die zweite „Nachname“.
Für Vorname reserviert der Programmierer maximal 8 Zeichen. Die gleiche Größe für den Nachnamen. Der Vorname bekommt die Adresse 20-27 und der Nachname die Adresse 28-35. Sie sind also Nachbarn im Speicher.
Nun schreibt jemand als Vorname BERNHART und als Nachname MÜLLER.
Wenn wir den Vor- Nachname auslesen, erhalten wir: BERNHART MÜLLER. Richtig!
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
B | E | R | N | H | A | R | T | M | Ü | L | L | E | R |
Vorname Nachname
Ein Angreifer versucht nun den Nachnamen zu ändern. Er weiß, dass der Vorname genau 8 Zeichen belegt. Er schreibt als Vorname: BERNHARTMEIER .
Das Programm übernimmt die Eingabe und schreibt den neuen Vornamen in die Tabelle.
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
B | E | R | N | H | A | R | T | M | E | I | E | R | R |
Da BERNDHARTMEIER zu lang ist, erzeugen wir einen Buffer Overflow.
Ruft jemand den Datensatz nun ab. Erhält er die fehlerhafte Ausgabe: BERNDHART MEIERR. Manipuliert via buffer overflow!
Das alles nur, weil der Programmierer vergessen hat, die Eingaben abzufangen und die Längenprüfung durchzuführen.
Einblick in den Stackbereich
Wir wissen, dass im Stackbereich Funktionen des Programms abgelegt werden. Weiterhin ist uns bekannt, dass man Speicherbereich überschreiben kann, wenn der Programmierer oder das System es zulässt. Weiterhin dürfen wir davon ausgehen, dass in den Programmen etliche Fehler stecken.
Wie wird nun eine Funktion im Stack angelegt:
Speicherbereich einer Funktion mit den Daten „buffer flow“.
Adresse | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Inhalt | b | u | f | f | e | r | f | l | o | w | ebp … | Rücksprungadresse x | … |
Speicherbereich der Funktion nach Manipulation
Adresse | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | ^3 | 14 | 35 |
Inhalt | 0x90 | 0x90 | shellcode | 0x90 | 0x90 | … | … | … | … | … | … | … | … | Adresse 1 | … |
Zur einfachen Darstellung verwenden wir keine „echten“ Adressen und die Buchstaben wären hexadezimale Werte.
ebp = Basiszeiger oder base pointer – Hier nicht weiter relevant
Rücksprungadresse: Ist die Adresse für einen Rücksprung beim Beenden der Funktion.
Realer Speicheraufbau einer 32 Bit Applikation
Adressermittlung von Funktionen.
Hier ein Beispiel.
Im nächsten Schritt muss man Fehler in dieser Applikation finden.
Die Suche nach dem Fehler
Ein trojanisches Pferd erwacht
Fehler im Automobil
Vorträge zum Thema
2: https://docs.microsoft.com/en-us/windows/win32/memory/heap-functions
3: https://www.blackhat.com/docs/us-16/materials/us-16-Yason-Windows-10-Segment-Heap-Internals-wp.pdf
4: https://de.wikipedia.org/wiki/Puffer%C3%BCberlauf inkl. Codebeispiele
Glossar:
DLL: Dynamic Link Library
Zero Day Exploit: Eine ausgenutzte Schwachstelle in der entsprechenden Software. Die Schwachstelle wird ausgenutzt, bevor sie vom Softwarehersteller durch einen Fix geschlossen werden kann.
Buffer overflow: Speicherüberlauf oder Pufferüberlauf
IDS: Intrusion Detection System; Als Intrusion-Prevention-Systeme werden bezeichnet, die über die reine Generierung von Ereignissen hinaus Funktionen bereitstellen, die einen entdeckten Angriff abwehren können.
IPS: Intrusion Prevention System; Ein System, das Anomalien oder Angriffsmustern erkennt und unterschiedliche Maßnahmen zur Abwehr des Angriffes ergreift. Es ist der Familie der IDS zuzuordnen.
CMD: Command oder auch als MS-DOS-Eingabeaufforderung bekannt
SHELL: Eingabeplattform zur Steuerung des System