Pufferüberlauf-Angriffe
Pufferüberlauf-Angriffe stellen eine erhebliche Bedrohung für die Softwaresicherheit dar. Diese Angriffe treten auf, wenn böswillige Personen Pufferüberlauf-Schwachstellen ausnutzen. Dies kann zu Programmabstürzen, Datenkorruption, Diebstahl von sensiblen Informationen und unbefugtem Systemzugriff führen. Dieser Artikel erklärt Pufferüberläufe, die Nutzung durch Angreifer und Methoden zu deren Prävention in der Softwareentwicklung.
Die Grundlagen von Pufferüberläufen
Ein Puffer ist im Kontext der Informatik ein Speicherbereich, der zur temporären Speicherung von Daten zugewiesen wird. Programme verwenden Puffer, um verschiedene Arten von Daten zu speichern, wie Benutzereingaben, Dateiinhalte oder Zeichenketten.
Jeder Puffer hat eine feste Größe. Probleme treten auf, wenn ein Programm versucht, mehr Daten zu speichern, als der Puffer aufnehmen kann. In solchen Fällen laufen die überschüssigen Daten über den Puffer hinaus und gelangen in benachbarte Speicherbereiche. Dieses unbeabsichtigte Verhalten kann zu Programmabstürzen, Datenkorruption und Sicherheitslücken führen.
Betrachten Sie das folgende Beispiel in der Programmiersprache C:
char buffer[8]; scanf("%s", buffer);
Dieser Code-Ausschnitt weist einen 8-Byte-Puffer zum Speichern einer von der Benutzereingabe erhaltenen Zeichenkette zu. Wenn der Benutzer mehr als 8 Zeichen eingibt, überschreibt er den benachbarten Speicher.
Ausnutzen von Pufferüberlauf-Schwachstellen
Angreifer nutzen Pufferüberlauf-Schwachstellen aus, indem sie gezielt Speicherbereiche überschreiben, die ausführbaren Code enthalten, und diesen durch bösartigen Code ersetzen. Der Angreifer identifiziert zunächst ein Programm mit einer bekannten Pufferüberlauf-Schwachstelle. Der Angreifer sendet absichtlich zu viele Daten, um das System zu überwältigen und einen Speicherfehler zu verursachen.
Der Angreifer möchte den Puffer mit bösartigem Code ersetzen. Dieser Code kann schädliche Aktionen ausführen, wie das Öffnen einer Shell oder das Ausführen von Befehlen ohne Erlaubnis. Der Angriff ist erfolgreich, wenn der Angreifer eine Rücksprungadresse oder einen Ausnahmebehandler ändert. Wenn der Benutzer den veränderten Code ausführt, wird der bösartige Code ausgeführt.
Um dieses Konzept zu veranschaulichen, betrachten Sie ein Serverprogramm, das Benutzernamen von Clients empfängt. Wenn der Speicherplatz für den Benutzernamen 128 Bytes beträgt, könnte ein Hacker einen schädlichen Benutzernamen in einem bestimmten Format senden.
"A" * 132 + bösartiger_code + gefälschte_rücksendeadresse
Die Reihe von “A”-Zeichen füllt den Puffer auf und ermöglicht dem bösartigen Code, in den Speicher zu schreiben. Die gefälschte Rücksprungadresse sorgt dafür, dass der bösartige Code ausgeführt wird, wenn die überschriebenen Funktionen zurückkehren.
Reale Beispiele für Pufferüberläufe
Jeder Pufferüberlauf-Angriff läuft nach der gleichen Strategie ab:
Hier sind einige reale Beispiele für Überlaufschwachstellen, die im Laufe der Jahre in bekannten DBMS gefunden wurden.
MySQL COM_FIELD_LIST
Bis 2012 waren MySQL und MariaDB anfällig für die COM_FIELD_LIST-Schwachstelle. Die Grundlagen der Schwachstelle waren wie folgt:
Der Täter würde eine Abfrage an den MySQL-Server mit einer ‘FROM’-Klausel durchführen, in der ein sehr langer Tabellenname angegeben ist, um einen Pufferüberlauf zu verursachen.
SELECT * FROM 'sehr_langer_tabellenname'.
Die genaue Länge wurde nicht angegeben, aber 5000 Bytes reichten aus, um einen Überlauf zu verursachen. Dies würde den Server zum Absturz bringen, aber in dem Moment zwischen dem Überlauf und dem Absturz wird der Server anfällig für Angriffe. Dies ist der Moment, in dem Täter bösartigen Code in hexadezimaler Byte-Form einfügen würden.
SELECT * FROM 'sehr_langer_name'.\x31\xc0\x50\x68\x2f\x2f\x73'
Der Code musste Bash-Befehle ausführen, z.B. ‘rm -rf /bin/’.
Für eine höhere Erfolgschance fügten Täter einen No Operation-Segment in den Code ein, also Code, der nichts ausführt.
Eine vollständige Abfrage würde so aussehen:
SELECT * FROM 'AAAAAAAAAAA..' verursacht Pufferüberlauf '\x0\x0\x0\x0\x0' - No-Operation Slide '\xe3\x50\x53\x89\xe1\xb0\x0b' - Bösartiger Code.
Die Schwachstelle wurde in den MySQL-Versionen 5.5.23, 5.1.63 und 5.6.6 sowie in den MariaDB-Versionen 5.5.23, 5.3.12, 5.2.14 und 5.1.63 behoben. Die Aktualisierung auf diese oder spätere Versionen hat die Schwachstelle behoben und die Datenbanken vor diesem spezifischen Angriff geschützt.
PostgreSQL 9.3 RESETXLOG-Pufferüberlauf
In ähnlicher Weise wurde 2013 entdeckt und schnell behoben, dass die Funktion pg_resetxlog() von PostgreSQL anfällig für diese Angriffe war.
postgres=# SELECT pg_resetxlog('A' * 1000 + *bösartiger_code*);
SQL Server Slammer Wurm
Der SQL Server Slammer Wurm-Angriff wurde 2003 entdeckt. Er zielte auf den SQL Server Resolution-Server ab, der UDP-Pakete auf Port 1434 akzeptiert. Wenn ein speziell gestaltetes Paket an diesen Port gesendet wurde, kam es zu einem Pufferüberlauf, der dem Wurm die Ausführung beliebigen Codes ermöglichte. Dieser Code veranlasste den Server, weitere Kopien des Wurms zu senden, was zu einer schnellen Verbreitung und massiven Netzwerküberlastungen führte. Ein Beispiel wäre so:
payload = create_malicious_packet() sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto('A' * 1000, *bösartiger_code*, (target_ip, 1434)) sock.close()
Oracle 9i XDB HTTP Pufferüberlauf
Im Jahr 2003 wurde eine Überlaufschwachstelle im Oracle Server entdeckt. Angreifer konnten einen sehr langen Benutzernamen in einer HTTP-GET-Anfrage senden, der den Puffer überfließen ließ und dann bösartigen Code ausführte.
long_username = 'A' * 1000 + *bösartiger_code* password = 'password' credentials = f"{long_username}:{password}" encoded_credentials = base64.b64encode(credentials.encode()).decode() http_request = ( "GET / HTTP/1.1\r\n" f" Host: {target_ip}\r\n" "User-Agent: Mozilla/5.0\r\n" f" Authorization: Basic {payload}\r\n" "Accept: */*\r\n" "\r\n" ) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((target_ip, target_port)) sock.sendall(http_request.encode())
Dieses Ausschnitt zeigt ein Python-Skript, das Anmeldeinformationen an den Oracle Server übermittelt, der seinen Puffer zum Überlaufen bringt. Infolgedessen führen die Anmeldeinformationen bösartigen Code aus.
Vermeidung von Pufferüberlauf-Schwachstellen
Die Entwicklung sicherer Software erfordert einen proaktiven Ansatz zur Vermeidung von Pufferüberlauf-Schwachstellen. Die folgenden Strategien sind entscheidend für die Minderung der Risiken durch Pufferüberläufe:
- Eingabevalidierung: Stellen Sie sicher, dass alle vom Benutzer gelieferten Daten innerhalb der erwarteten Grenzen liegen, bevor Sie diese in Puffern speichern. Validieren Sie Eingabelänge, Format und Inhalt, um zu verhindern, dass bösartige oder unbeabsichtigte Daten Pufferüberläufe verursachen.
- Sichere Zeichenketten- und Speicherfunktionen: Vermeiden Sie die Verwendung von Standardbibliotheksfunktionen, die anfällig für Pufferüberläufe sind. Verwenden Sie stattdessen sicherere Alternativen wie `strncpy` und `memcpy_s`, die eingebaute Sicherungen gegen Überläufe enthalten.
- Systemebene-Schutzmaßnahmen: Aktivieren Sie, wann immer möglich, Sicherheitseigenschaften auf Systemebene, wie z.B. Address Space Layout Randomization (ASLR) und Data Execution Prevention (DEP). Diese Mechanismen erschweren es Angreifern, Speicherlayouts vorherzusagen und bösartigen Code auszuführen.
- Verwenden Sie speichersichere Programmiersprachen wie Rust, Go oder Java, um Pufferüberläufe zu verhindern. Diese Sprachen erzwingen strikte Speicherverwaltungspraktiken und verhindern den direkten Zugriff auf Speicher, wodurch das Risiko von Überlaufschwachstellen verringert wird.
- Regelmäßige Software-Updates: Aktualisieren Sie Softwarebibliotheken und Abhängigkeiten umgehend, wenn Pufferüberlauf-Schwachstellen entdeckt und Patches veröffentlicht werden. Auf dem neuesten Stand mit den neuesten Sicherheitspatches zu bleiben, ist entscheidend für den Schutz vor bekannten Schwachstellen.
Der Einsatz von Fuzz-Tests und SAST-Techniken wie Taint-Analyse kann helfen, Pufferüberlauf-Bugs während der Softwareentwicklung zu finden.
Reale Auswirkungen von Pufferüberlauf-Angriffen
Im Laufe der Computergeschichte haben Hacker zahlreiche hochkarätige Sicherheitsvorfälle auf Pufferüberlauf-Schwachstellen zurückgeführt. Der Morris-Wurm war ein früher Internet-Wurm, der sich 1988 verbreitete, indem er eine Sicherheitslücke im Unix `Finger`-Programm ausnutzte.
Im Jahr 2017 nutzte das WannaCry-Virus eine Schwachstelle im Windows Server Message Block-Protokoll aus, um sich zu verbreiten. Innerhalb eines einzigen Tages infizierte WannaCry weltweit über 230.000 Computer und verursachte erhebliche finanzielle Verluste und Störungen.
Fazit
Pufferüberlauf-Angriffe bleiben eine kritische Sorge im Bereich der Softwaresicherheit. Entwickler können ihre Software vor Angriffen schützen, indem sie sich über Pufferüberläufe und deren Ausnutzung durch Angreifer informieren.
Es ist wichtig, sichere Programmierpraktiken zu verwenden. Diese Praktiken umfassen Eingabevalidierung und sichere Speicherfunktionen. Sie helfen, Pufferüberlauf-Schwachstellen in Systemen zu verhindern. Der Einsatz speichersicherer Programmiersprachen und die regelmäßige Aktualisierung von Softwareabhängigkeiten erhöht zusätzlich die Widerstandsfähigkeit von Softwaresystemen.
Softwareentwickler können die Sicherheit digitaler Systeme verbessern, indem sie Pufferüberläufe verhindern und sich neuer Bedrohungen bewusst bleiben. Dies schützt Daten und stellt sicher, dass Computersysteme zuverlässig bleiben.