Hacker im Dunkeln vor Programmcode.

Warum Schwachstellen in Software kaum vermeidbar sind

Angriffe auf Computersysteme gehören mittlerweile zum Alltag – sie finden quasi rund um die Uhr statt. Die Aufmerksamkeit der Medien – und somit einer breiteren Öffentlichkeit – erregen sie nur noch, wenn sie entweder einen besonders brisanten Hintergrund haben oder ihre Auswirkungen eine überdurchschnittliche Tragweite erreichen. Ein Beispiel für ersteres sind die jüngsten Angriffe auf öffentliche und gewerbliche Rechnersysteme im Zusammenhang mit dem Krieg in der Ukraine. Ein Beispiel für das Zweite etwa die Ende 2021 bekannt gewordenen Angriffe auf eine große Anzahl von Systemen und Diensten, die auf einer Schwachstelle der Java-Bibliothek Log4j basierten.

Übrigens wird auch diese Lücke aktuell immer noch und nicht zuletzt im Zusammenhang mit Attacken auf Systeme ukrainischer Behörden ausgenutzt. Allerdings kann man sich schon fragen: Warum gibt es die viel zitierten Schwachstellen in Software eigentlich überhaupt – und das in so großer Zahl? Und warum ist es offenbar kaum möglich, sie zu vermeiden?

Aufmacherbild: Pixabay/Gerd Altmann
Autor: Stefan Achleitner

Was im Deutschen als „Schwachstellen“ bezeichnet wird, heißt auf Englisch „vulnerabilities“, wörtlich: Verletzlichkeiten. Und dieser Begriff trifft den Sachverhalt eigentlich noch besser: Moderne Software ist verletzlich. In diesem Artikel möchten wir beleuchten, warum das so ist. Und warum Schwachstellen in Software so schwer zu verhindern sind.

Komplexität verursacht Anfälligkeiten

Der wesentliche Grund: Software ist komplex. Und sie wird immer komplexer. Größere, moderne Softwareprogramme haben oftmals hunderttausende Zeilen Programmcode. Allein diese schiere Masse macht es praktisch unmöglich, jeden denkbaren Fall vorab zu testen. Es ist kaum zu leisten, die Software auf alle möglichen Fehler beziehungsweise ungewolltes Verhalten zu überprüfen. Daher bleibt den Anbietern keine andere Wahl als bei erkannten Fehlern oder Schwachstellen schnellstmöglich Patches und Updates zu liefern.

Aus diesem Grund wird heutzutage Software auch laufend mit Patches und Updates versorgt. Und deshalb ist es auch so wichtig, dass Administratoren beziehungsweise Nutzer diese Patches von Betriebssystemen und Anwendungsprogrammen schnellstmöglich auf ihren Rechnern einspielen.

Wie sich scheinbar naheliegende Programmfunktionen zweckentfremden lassen

Besonders problematische Auswirkungen können ungewollte Programmfunktionen haben, wenn sich daraus Sicherheitslücken ergeben. In der Regel bedeutet dies, dass Angreifer Zugriff auf Daten oder Funktionen erlangt, zu denen dieser Nutzer eigentlich nicht befugt ist.

Oft resultiert so eine Sicherheitslücke daraus, dass ein Programm Benutzereingaben direkt verarbeitet, ohne diese genauer zu evaluieren. Die grundsätzlichen Zusammenhänge und Wirkungsweisen illustriert das folgende Beispiel. Es demonstriert, wie eine zu einfach konzipierte Passwortabfrage in der Datenbank-Programmiersprache SQL zu einer Schwachstelle führen würde.

Im untenstehenden Bild sehen Sie ein typisches Login-Fenster, das die Abfrage von Benutzernamen und Passwort durchführt. Im selben Bild darunter: die Datenbankabfrage, welche die Benutzereingaben in den Feldern „Benutzername“ und „Passwort“ direkt in SQL-Programmcode umwandelt.

Beispiel für eine Software-Schwachstelle.
Das Problem: Die abgefragten und vom Benutzer eingegebenen Parameter verarbeitet der beispielhafte SQL-Code direkt und ungeprüft.

Schwachstellen in Software: Mit cleveren Tricks zum unberechtigten Zugriff

Diese Vorgehensweise der Software erscheint zwar auf den ersten Blick naheliegend und logisch. Tatsächlich öffnet sie aber ein riesiges Einfallstor für Angreifer. Warum das so ist, zeigt das nächste Bild.

So funktioniert die beispielhafte SQL-Schwachstelle.
Mit cleveren Eingaben kann der Angreifer die Prüfung von Benutzername und Passwort umgehen. Gleichzeitig zeigt seine Eingabe die Liste aller Benutzer und ihrer weiteren Details an.

Mit einer clever manipulierten Eingabe kann der Angreifer die Prüfung von Benutzername und Passwort umgehen. Gleichzeitig zeigt seine Eingabe die Liste aller Benutzer und ihrer weiteren Details an.

Denn passt ein Angreifer seine Eingaben in den Feldern Benutzername und Passwort geschickt an, kann er die daraus generierte SQL-Abfrage manipulieren. So verändert der Hacker den tatsächlich ausgeführten Programmcode in seinem Sinne.

Wie gezeigt, hat der Angreifer dazu im Feld „Benutzername“ den Text „or 1=1; /“ und im Feld „Passwort“ den Text „*/–“ eingegeben. SQL interpretiert die Eingabe or 1=1 fatalerweise als Teil des Programmcodes. Dies hebelt die eigentlich vorgesehene Überprüfung des Benutzernamens aus. Denn nun gilt: Entweder muss der Name des Benutzers in der entsprechenden Liste stehen ODER die Bedingung „1=1″ muss zutreffen. Da letzteres immer der Fall ist, spielt es keine Rolle mehr, ob der Benutzername in der Berechtigungsliste enthalten ist oder nicht.

Die zugehörige Überprüfung des Passworts hebelt die kreative Hacker-Eingabe ebenfalls aus: Das Einfügen von /* und */– wandelt den ursprüngliche Programmbefehl für den Passwortcheck einfach zu einem Kommentar um. SQL interpretiert diesen kritischen Programmteil somit nur noch als reine Programmierer-Anmerkung. Ausgeführt werden die zwischen den Zeichen /* und */– stehenden Befehle nicht mehr.

Die so resultierende SQL-Abfrage würde nun einem Angreifer die gesamte Benutzertabelle mit allen Details zurückgeben. Dies wäre ein verheerender Cyberangriff. Denn nun hätte der Hacker die tatsächlichen Benutzerdaten und könnte sich anschließend als berechtigter User im System anmelden.

Jede Art von Eingaben ist potenziell kritisch

Das gezeigte Beispiel ist zur Veranschaulichung recht einfach gehalten. Trotzdem zeigt es, wie das grundsätzliche Ausnutzen einer Software-Schwachstelle funktioniert.

Eine gut entworfene Software würde solche Angriffe verhindern, indem sie Benutzereingaben nicht direkt in einer Datenbankabfrage verwendet. Vielmehr sollte sie die Eingaben zuerst auf bestimmte Zeichenfolgen untersuchen. Erkennt sie kritische Eingaben, die zum skizzierten Fehlverhalten führen würden, würde sie die Weitergabe an den ausführenden Programmcode verhindern.

Das Beispiel der SQL-Abfrage zeigt, welch komplexe Angriffs-Szenarien Programmierer zum Schutz ihrer Software unterbinden müssen. Und manipulierte Benutzereingaben sind nur eine von vielen Möglichkeiten, wie Hacker Schwachstellen in Software ausnutzen können.

Denn grundsätzlich lässt sich jede externe Quelle, aus der eine Software Daten liest, so manipulieren, dass sie eine bestimmte unerwünschte Funktion herbeiführt. Dies kann etwa auch durch Datenpakete geschehen, die eine Applikation über das Netzwerk empfängt. Oder durch die Inhalte von Dateien, die ein Programm einliest.

Die konkrete Schwachstelle bei Log4j

Wird durch das Einlesen von manipulierten Daten eine Schwachstelle in einer Anwendung ausgenutzt, lässt sich zwischen verschiedenen Angriffszielen unterscheiden. Handelt es sich wie im oben gezeigten Beispiel um SQL, zielt der Angriff meist auf Datendiebstahl ab. Durch das Einfügen von Programm- oder Shellcodes können Hacker oftmals eine bestimmte Funktion in einer Applikation herbeiführen, die so eigentlich nicht vorhanden sein sollte.

Ein sehr aktueller Fall ist die bereits eingangs erwähnte Schwachstelle in der Java-Bibliothek Log4j. Die Bibliothek, deren Name ausgeschrieben für „Logging for Java“ steht, nutzen viele Programme zum Protokollieren („Logging“) von Programmaktionen. Dazu zählt auch das Protokollieren bestimmter Eingaben, die von externen Quellen stammen. Zum Beispiel Teile von Datenpaketen oder auch die Namen von Benutzern, die sich eingeloggt haben.

Das Problem der Schwachstelle in Log4j ist, dass Text wie ‘${variable}’ bei manchen Versionen der Bibliothek nicht nur geloggt, sondern auch interpretiert wird. Grundsätzlich geht die Schwachstelle also in eine sehr ähnliche Richtung wie unser SQL-Beispiel.

So führt die Log4j-Bibliothek dann Eingaben wie zum Beispiel „${sys:os.name}“ als Programmanweisung aus. Das angegebene Beispiel liest dabei „nur“ den Namen des Betriebssystems aus. Wirklich gefährlich wird diese Schwachstelle jedoch dadurch, dass Angreifer durch Ausnutzung von Befehlen an das „Java Naming and Directory Interface“ (JNDI) Netzwerkverbindungen zu externen Servern herstellen können. Auf diesem Weg kann der Angreifer weitere Malware auf den Host-Computer laden. So führt er dann weitere Schritte seines Angriffs aus:

So funktioniert die Schwachstelle in Log4j.
Die Schwachstelle in Log4j kann Malware von fremden Servern herunterladen und ausführen. (Icons im Bild von (https://www.flaticon.com/, https://www.iconarchive.com)

Schwachstellen wird es in Software immer geben

Die beschriebene und in neueren Versionen von Log4j mittlerweile behobene Schwachstelle war besonders problematisch, weil diese Logging-Bibliothek sehr weit verbreitet ist. Nach Bekanntwerden der Sicherheitslücke war es für Angreifer zudem sehr leicht, sie auszunutzen. Davon abgesehen war dieser Fall aber gar nicht besonders außergewöhnlich.

Fast täglich werden neue Schwachstellen und Sicherheitslücken in Programmen und auch Betriebssystemen entdeckt. Eine zuverlässige Quelle hierfür ist das System „Common Vulnerabilities and Exposures“ (CVE). Übersetzt bedeutet dieser Name „Bekannte Schwachstellen und Anfälligkeiten“. Das Projekt strebt eine zentrale Katalogisierung und eine einheitliche Namensgebung für quasi alle bekannt gewordenen Software-Schwachstellen an.

Unter www.cvedetails.com können Interessierte nachschauen, was in den von ihnen genutzten Programmen und Systemen gefunden wurde. Die Website zeigt außerdem Statistiken über die Häufigkeit und Schwere der entdeckten Lücken.

Allerdings sollte Nutzern und Programmierern immer klar sein: In wohl ebenso großer Zahl gibt es eben auch unentdeckte beziehungsweise noch nicht auf breiter Front bekannte Sicherheitslücken. Das Katz-und-Maus-Spiel zwischen Angreifern und Sicherheits-Experten wird deshalb ungebremst weitergehen.

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.