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.

Ein Programm hat ein Eingabefeld. Für das Feld sind 250 Zeichen reserviert. Wenn man nun 251 Zeichen einfügt, ist fraglich, was mit dem 251 zigsten Zeichen passiert. Es wäre eigentlich die Pflicht des Programmierers, solche Überläufe zu kontrollieren.
Das ist aber nicht immer einfach.
  1. Um es anschaulich darzustellen, ein Beispiel:
 
Sie schreiben einen Brief mit 900 Zeichen. Wie viele Rechtschreibfehler bzw. grammatikalische Ungereimtheiten haben sich in diesen Brief eingeschlichen? Wenn ein Außenstehender den Brief lesen würden, dann findet dieser sicherlich mindestens einen Fehler. Nun stellen Sie sich vor, dass ein Programm aus 40 Millionen Zeichen und mehr besteht. Denken Sie wirklich, dass alles fehlerfrei ist? Diese Annahme wäre wohl sehr naiv. Windows 10 hat mindestens 50 Millionen „lines of codes“ also Zeilen voll mit Zeichen. Hinzukommt, dass man altbewährte Funktionen und Bibliotheken wiederverwendet. Diese werden i.d.R. kaum geprüft und ohne weitere Überlegungen eingebunden. Warum auch das Rad neu erfinden, wenn es das Rad bereits gibt.

Das ist eine Ursache, dass die Software, welche wir nutzen, mit hoher Sicherheit etliche Fehler hat.

Funktionsweise des buffer overflows

Wir beginnen wieder mit einem einfachen Beispiel. Der Angreifer kennt einen Fehler bei einem gängigen PDF-Reader. Er sendet Ihnen ein PDF per E-Mail zu. Sie öffnen das Dokumente und der PDF-Reader auf Ihren PC startet wie gewünscht. Das nun geöffnete Programm versucht das PDF aus der E-Mail darzustellen. Der Angreifer hat ein Feld mit mehr Zeichen befüllt als erlaubt oder hat Ihnen ein Dokument gesendet, das ein sehr großes Bild beinhaltet, welches die Applikation so nicht erwartet. Was geschieht nun mit dem Überlauf. Er rinnt – Analogie zum Wasser- unkontrolliert in andere Speicherbereiche. Was er dort tut, werden wir später sehen. Wir Ihr Programm nun noch mit Adminrechten ausgeführt, dann kann das Produkt etliche Änderungen an Ihrem PC vornehmen.
 
Damit wir das verstehen, sehen wir uns den Speicherausbau eines Windows-PCs an.

Der Speicherausbau

 
Damit ein Programm arbeiten kann, braucht es einen Speicher. Dazu legt Windows einen virtuellen Speicherbereich an. Jedes Programm hat also seinen eigenen virtuellen Speicherbereich.
 
Bitte lassen Sie nicht irritieren von der Darstellung z. B. 0xffffffff. Es spielt keine Rolle für das Verständnis. Es ist die Darstellung von hexadezimalen Werten, die in der IT durchgängig verwenden finden.

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.

Es gibt mehrere Möglichkeiten, um den Schadcode auszuführen. Wir beschreiben hier nur eine Variante.
Als Beispiel eine reale Aufnahme vom Stack:

Realer Speicheraufbau einer 32 Bit Applikation

Adressermittlung von Funktionen.

Hier ein Beispiel.

Im nächsten Schritt muss man Fehler in dieser Applikation finden.

Dass wir uns im Stackbereich befinden, sieht man an der Adresse. Die Funktion beginnt mit 0x76700000 und Ende mit der Adresse 0x76721000.
Es zeigt sehr deutlich, dass man von jedem Programm die Parameter finden kann.

Die Suche nach dem Fehler

Angreifer suchen nach Schwachstellen in einem beliebten Softwareprodukt. Das können Office- Browser- E-Mail- PDFReader-Programme, Webserver usw. sein. Bei der Vielzahl von verwendeten Produkten, ist es nicht schwer, irgendwo einen Fehler zu finden. Man braucht nur Zeit und Ausdauer.
Sinngemäß muss man nun den Speicher (hier: Stackbereich) überschreiben, wie in unserem obigen Beispiel gezeigt.  Die Speicherzellen füllt man mit NOP (no operations – code 0x90) und dem Schadcode. Die Rücksprungadresse verändert man auf eine andere Adresse. In unserem Beispiel auf die 1.  Die Funktion wird ausgeführt. NOP Codes werden vom Programm „übersprungen. Erstmals passiert nichts. Dann ist die Funktion beendet und springt auf die manipulierte Adresse (hier 1) zurück. Dort befindet sich unser platzierter Schadcode.

Ein trojanisches Pferd erwacht

Das System wird das Programm ausführen. Das kann z.B. auch der Aufruf eines SHELL-Codes sein. Die Shell kann evtl. Programme nachladen und installieren. Ein Trojaner ist jetzt auf Ihrem PC gelandet und Ihre Tätigkeiten und Handlungen werden ggf. überwacht.
Das Beispiel ist sehr einfach dargestellt. Dennoch zeigt es, dass es wichtig ist, dass man seine Programme aktualisiert. Die Hersteller schreiben sog. Bounty Programme aus. Diese dienen dazu, dass versierte Hacker Fehler suchen und dem Hersteller melden. Dieser korrigiert (hoffentlich) die Schwachstelle und verbessert seine Software durch ein Update.
Microsoft, Apple und Google verbessern den Schutz stetig. Besonders in modernen Programmentwicklungsumgebungen kann man entsprechenden Schutzmaßnahmen veranlassen. Auch hier spielt das Update eine große Rolle. Aber manche Programmierer unterlassen beispielsweise die automatisierte Längenprüfung zugunsten der Geschwindigkeit.
Fazit: Aktualisieren Sie Ihr System. Öffnen sie nicht wahllos alle Anhänge in E-Mails und besuchen sie keine dubiosen Seiten mit Ihrem Browser. Vielleicht können Sie auch ein virtuelles System benutzen, wenn Sie auf Reisen mit Ihrem Browser gehen. Alle Programme können von einem buffer overflow betroffen sein. Die Überschreibung des Speichers kann auch in anderen Segmenten geschehen. Selbst Übergabeparameter können verändert werden.
Virenscanner können helfen. Meist jedoch kennt der Scanner sehr aktuelle Bedrohung gar nicht. Große Organisationen arbeite mit „unbekannten“ Lücken (Zero-Day-Exploits), um in ein System einzudringen.

Fehler im Automobil

Wer nun denkt, dass buffer overflow nur in heimischen Computer vorkommt, der irrt. Moderne Fahrzeuge steuern ihre Systeme über BUS-Systeme (beispielsweise Can Bus oder Lin Bus) und Steuergeräte. Hier findet man Dutzende von Softwarefehlern. Heutzutage können wir immer noch tief ins Auto eindringen, wenn wir Zugriff auf den Can-Bus erhalten, was nicht sonderlich schwer ist. Darum gilt auch hier. Ihr Auto braucht immer wieder ein Software-Update.

Vorträge zum Thema

Wir veranstalten auch praxisnahe Vorträge zu diesem Thema.
Quellen:

1: https://www.microsoft.com/security/blog/2020/07/08/introducing-kernel-data-protection-a-new-platform-security-technology-for-preventing-data-corruption/

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

Post by Digitales Erbe

Comments are closed.