SQL-Injection: Teamwork unter Parametern macht’s möglich

Home / Blog / SQL-Injection: Teamwork unter Parametern macht’s möglich

Eine Einführung ins Thema SQL-Injections findet ihr in unserem vorherigen Beitrag.

SQL-Injections sind vermutlich genauso alt wie die ersten Datenbanken. Trotz ihrer Bekanntheit und bewährten Gegenmaßnahmen stoßen wir aber immer wieder auf diese Schwachstelle.

SQL-Injections entstehen, wenn Benutzereingaben direkt in Datenbankabfragen verwendet werden. Dies kann ausgenutzt werden, um die Abfrage (fast) beliebig anzupassen, um so beispielsweise an Daten zu gelangen, die eigentlich nicht zugreifbar sein sollten.

Vergleichen kann man das mit einem Blankoscheck. Der Aussteller gibt die Kontrolle über die eingetragene Summe ab. Der Empfänger kann einen (fast) beliebigen Geldbetrag eintragen und diesen vom Aussteller-Konto abheben. In vertrauensvollen Hände ist das bequem – in den falschen Händen kann das aber fatale Folgen haben.

Die Ausgangslage

In unseren Pentests sehen wir im Wesentlichen 3 Fälle, wenn es um das Vorbeugen von SQL-Injection-Schwachstellen geht:
  1. Das Thema wurde nicht bedacht, d.h. es gibt keinen Schutz. Dann ist die Ausnutzung in der Regel einfach.
  2. Es werden vorgefertigte Prepared Statements korrekt verwendet, die vor SQL-Injection-Schwachstellen schützen, mehr dazu unten.
  3. Vor der Verwendung von Benutzereingaben werden eigene Versuche unternommen, die im Wesentlichen auf 2. abzielen, aber leider meist Lücken enthalten.
Im Folgenden geht es um den 3. Fall und den kreativen Prozess, an den eingebauten Hürden vorbei zur Ausnutzung der Schwachstelle zu kommen.
Die Abbildung zeigt genau so einen Versuch. In Zeile 6 werden Wörter und Zeichen definiert, die häufig in SQL-Injection-Angriffen verwendet werden. In Zeile 7 werden in den empfangenen Benutzereingaben, in diesem Fall username und password, die definierten Wörter entfernt. Die resultierenden Werte werden dann in Zeile 10 in die Datenbankabfrage eingesetzt und ausgeführt.
Fehlerhafter Filter zur Vorbeugung von SQL-Injections.

Typische Schwächen in implementierten Filtern

Der obige implementierte Filter ist nicht so effektiv, wie er auf den ersten Blick scheinen mag. Mehrere „Tricks“ können kombiniert werden, um schlussendlich eine erfolgreiche SQL-Injection durchzuführen.

Groß- und Kleinschreibung
Groß- und Kleinschreibung ist bei Datenbankabfragen in der Regel egal. SELECT kann also einfach durch select ersetzt werden. Der implementierte Filter beachtet aber die unterschiedlichen Schreibweisen nicht. Übrigens akzeptiert eine Datenbank auch eine gemischte Schreibweise, wie etwa SeLEct.

Verhalten des Filters einbeziehen In manchen Fällen wird die Groß- und Kleinschreibung korrekt beachtet. Oft wird das Ersetzen der gefährlichen Wörter und Zeichen aber nur genau einmal angewendet. Was passiert also, wenn die Eingabe beispielsweise SELSELECTECT enthält? Nach dem Entfernen des Inneren SELECT bleibt selbiges übrig und passiert den Filter ungehindert, da dieser nicht erneut auf das Ergebnis angewendet wird.

Anführungszeichen escapen
Eine weitere Hürde im implementierten Filter ist das Ausschließen des einfachen Anführungszeichens (‚). Dieses wird in der Regel benötigt, um aus einem String-Kontext in der Datenbankabfrage auszubrechen, um so die eingeschleusten SQL-Schlüsselwörter zur Ausführung zu bringen. Die beiden vorherigen Tricks lassen sich auf das Anführungszeichen nicht anwenden.

Trotzdem lässt sich der Filter umgehen, indem man einen Backslash (\) nutzt, um das Anführungszeichen zu escapen. Der Backslash wird vom Filter nicht beachtet und bleibt in der Benutzereingabe deshalb erhalten. Escapen bedeutet, dass ein Zeichen als tatsächlich dieses Zeichen betrachtet wird und nicht als Teil der SQL-Abfrage interpretiert wird, um beispielsweise einen String-Kontext zu beenden. Der Text 'You\'re welcome.' wird von der Datenbank also als String You're welcome. verwendet.

Der Trick

Wie lässt sich mit den erläuterten Schwächen nun aber der implementierte Filter umgehen, sodass man eine manipulierte Datenbankabfrage ausführen kann? Die Datenbankabfrage aus dem Beispiel hat die folgende Struktur:
SELECT * FROM users WHERE name = '<username>' AND password = '<password>'
Beim Aufruf des obigen Codes wählen wir die Parameter wie folgt:
username: MindBytes\
password:  or 1=1 -- comment
Der implementierte Filter erkennt den Backslash (\) und das or nicht und fügt beides in die Datenbankabfrage ein:
SELECT * FROM users WHERE name = 'MindBytes\' AND password = ' or 1=1 -- comment'
Für die Datenbank hat diese Abfrage jedoch die folgende Struktur:
SELECT * FROM users WHERE name = 'MindBytes\' AND password = ' or 1=1 -- comment'
Da das Anführungszeichen hinter MindBytes escapt wird, bekommt die WHERE-Bedingung eine unerwartete Form. Der Parameter password wird dann genutzt, um die Datenbankabfrage zu manipulieren. Hier muss man den SQL-Injection-Filter bedenken und beispielsweise die fehlende Erkennung von Groß- und Kleinschreibung zum eigenen Vorteil nutzen. Weiterhin wird das Ende der vordefinierten Datenbankabfrage durch einen Kommentar (–) unwirksam gemacht. Die Datenbankabfrage gibt so alle Einträge aus der Tabelle users aus, da wir eine OR-Bedingung einfügen konnten, welche dazu führt, dass die WHERE-Bedingung immer wahr ist. Über die gleichzeitige Manipulation der beiden Parameter username und password sind wir also am Filter vorbeigekommen.

Die Auswirkung

Mit einer SQL-Injection lassen sich unterschiedliche Dinge erreichen. Oftmals sind neben den enthaltenen Informationen in der Datenbank auch weitere Funktionen der Datenbanken selbst interessant. Mögliche Ziele eines Angreifers können sein:
  • Manipulation von Abläufen, bspw. Login ohne gültige Zugangsdaten.
  • Unbefugter Zugriff auf Daten innerhalb derselben Datenbank oder weiteren verfügbaren Datenbanken.
  • Je nach Art der verwundbaren Datenbankabfrage können Daten verändert oder gelöscht werden.
  • Überlasten der Datenbank, beispielsweise durch Ressourcen-hungrige Abfragen, um die Verfügbarkeit zu stören.
  • Je nach Konfiguration und Berechtigungen des Datenbankbenutzers können Datenbank-Funktionen missbraucht werden, welche das Lesen oder Schreiben von Dateien auf dem Dateisystem, das Ausführen von Betriebssystem-Befehlen oder das Stellen von Netzwerk-Anfragen, beispielsweise an interne Systeme, ermöglichen.

Die Lösung: Prepared Statements

SQL-Injections sind ein generelles Problem mit einer generellen Lösung: Prepared Statements. Ein selbst entwickelter Filter ist also gar nicht nötig. Hier besteht die Gefahr, dass man Schlüsselwörter oder Zeichen nicht beachtet – wie oben demonstriert. Prepared Statements sind für die gängigen Programmiersprachen und Datenbanken verfügbar und überlassen es der Datenbank selbst, die Benutzereingaben richtig zu verarbeiten.

Bei der Verwendung von Prepared Statements wird zunächst die Struktur der Datenbankabfrage definiert. An Stellen, an denen Benutzereingaben verwendet werden, müssen Platzhalter eingefügt werden. Diese werden durch Fragezeichen in der Datenbankabfrage dargestellt (Zeile 6).

Beim Ausführen der Abfrage werden der Datenbank nun die Struktur der Abfrage und die Benutzereingaben separat übergeben (Zeile 7).

Beim Ausführen Datenbankabfrage ist somit klar, welche Bestandteile vom Benutzer stammen und keinen Einfluss auf die Abfragelogik haben dürfen.

Entwickler und Entwicklerinnen können sich an dieser Stelle also ganz auf erprobte Gegenmaßnahmen von der Datenbank selbst verlassen.

Nutzung von Prepared Statements zum verhindern von SQL-Injections.

Bereit für mehr IT-Sicherheit?

Dann nutze unseren Konfigurator, um ein passendes Angebot anzufordern oder schreibe uns, um ein individuelles Angebot zu erhalten.