Dienstag, 9. November 2010


Topthema

Mittwoch, 8. Oktober 2008 | Topthema

About Security #176: Schwachstellen-Suche: SQL-Injection verhindern

(Link zum Artikel: http://www.entwickler.de/entwicklerde/kolumnen/045452)

SQL-Injection kann durch die Filterung der Benutzereingaben und dem Einsatz von Prepared Statements verhindert werden. Worauf dabei zu achten ist, erfahren Sie in dieser Folge.

Benutzereingaben filtern

Wie bereits in About Security #172 zu sehen war, können Filter unter Umständen umgangen werden. Trotzdem sind sie keineswegs überflüssig. Zum Einen spricht nichts dagegen, sie so sicher wie möglich zu implementieren, zum Anderen erschweren sie Angriffe auch dann, wenn sie nicht perfekt sind. Im folgenden werden die häufigsten Fehler bei der Implementierung von Filtern aufgeführt.

Numerische Daten

Numerische Daten, die direkt in die SQL-Abfrage übernommen werden, werden meist nicht in '-Zeichen eingeschlossen. Wie in About Security #168 zu sehen war, macht das SQL-Injection-Angriffe besonders einfach. Wenn sicher ist, das ein bestimmter Parameter nur Zahlen enthalten darf, spricht nichts dagegen, die Eingaben in Werte des betreffenden Datentyps umzuwandeln.

SQL-Injection 2. Ordnung

Security aktuell
T�glich aktuelle Security-Infos!

Wie in About Security #174 zu sehen war, können auch korrekt durch Einfügen von Escape-Zeichen abgesicherte Eingaben in einem weiteren Schritt zu SQL-Injection führen. Vom Benutzer gelieferte Daten müssen immer als möglicherweise manipuliert betrachtet werden. Nur weil sie zwischendurch in der Datenbank gespeichert wurden, sind sie nicht harmlos. Je nach Verwendung der Daten muss daher darauf geachtet werden, das evtl. entfernte Quote-Zeichen vor der erneuten Verwendung in einer SQL-Abfrage wieder eingefügt werden.

Einfaches Filtern reicht nicht

In About Security #172 wird beschrieben, wie sich einfache Filter austricksen lassen, indem die Eingabe anders als üblich kodiert oder geschrieben wird. Das beste Beispiel für so einen Fall ist ein Filter, der unerwünschte SQL-Schlüsselwörter wie z.B. SELECT löscht. Wird der Filter nur einmal angewendet, kann er evtl. durch Eingabe von SELESELECTCT ausgetrickst werden: Das innere SELECT wird gelöscht, und übrig bleibt SELECT. Selbst eine mehrfache Anwendung dieses Filters würde nicht helfen, der Angreifer muss das gewünschte Schlüsselwort nur einmal mehr ineinander verschachtelt eingeben als die Filterfunktion aufgerufen wird. Werden Teile der Eingabe gelöscht statt sie komplett zu verwerfen, muss der verbleibende Rest erneut geprüft werden. Es darf nicht davon ausgegangen werden, das er nach dem Löschen unerwünschter Teile keine Gefahr mehr darstellt.

Stored Procedures sind keine Lösung

Stored Procedures schützen nicht vor SQL-Injection: Zum einen können sie selbst SQL-Injection-Schwachstellen enthalten, zum anderen kann auch eine eigentlich sichere Stored Procedure unsicher aufgerufen werden. Zum Beispiel könnte eine als Stored Procedure gespeicherte Abfrage folgendermaßen aufgerufen werden:

exec sp_Abfrage 'irgendwas'

Diese Abfrage ist ebenso einfach angreifbar wie ein einfaches SQL-Statement. Der Angreifer könnte z.B. folgendes als Wert für den Parameter eingeben:

egal'; exec master..xp_cmdshell '[Anweisung]'--

Das würde dann zu folgenden Aufruf führen:

exec sp_Abfrage 'egal'; exec master..xp_cmdshell '[Anweisung]'--'

Je nach Art der Anweisung könnte so z.B. ein neuer Benutzer angelegt oder Schadcode nachgeladen werden. Stored Procedures sind also von sich aus kein Schutz vor SQL-Injection, sie müssen zum einen selbst sicher sein und zum anderen dürfen sie nur mit sicheren Werten aufgerufen werden.

Sicher: Prepared Statements

Den besten Schutz von SQL-Injection bieten die auch als parametrisierte Aufrufe (parameterized queries) bezeichneten Prepared Statements. Der Aufbau des SQL-Statements wird dabei in zwei Schritte aufgespalten:

  1. Die Struktur der Abfrage wird definiert, für alle Eingaben werden Platzhalter eingesetzt.
  2. Der Inhalt der Platzhalter wird spezifiziert.

Die im zweiten Schritt erzeugten Daten haben keine Möglichkeit, die im ersten Schritt definierte Struktur der Abfrage zu ändern. Nachdem die Struktur der Abfrage definiert wurde, werden alle für die Platzhalter übergebenen Daten als Daten und nicht als Teil der Statement-Struktur betrachtet. Schleust ein Angreifer SQL-Code ein, wird er nicht ausgeführt (siehe auch About Security #13).

Prepared Statements sicher nutzen

Prepared Statements sind nur dann sicher, wenn sie konsequent für alle SQL-Abfragen verwendet werden. Werden sie nur für die Abfragen verwendet, die direkte Benutzereingaben enthalten, ist z.B. SQL-Injection 2. Ordnung möglich. Außerdem müssen alle Eingaben parametrisiert werden. Werden einige Eingaben direkt übernommen, ist darüber SQL-Injection möglich.

Keine Tabellen- und Spaltennamen als Platzhalter
About Security: Die komplette Serie

Platzhalter können nicht als Tabellen- und Spaltennamen verwendet werden. Müssen Tabellen- oder Spaltennamen aus Benutzereingaben übernommen werden, ist das nur direkt möglich. Den besten Schutz vor SQL-Injection bietet in diesem Fall eine Whitelist: Nur bekannte Tabellen- und Spaltennamen werden in die Abfrage übernommen, alles andere wird verworfen.

Defense in Depth

Falls es trotz aller Schutzmaßnahmen doch einmal zu SQL-Injection kommt, helfen einige einfache Maßnahmen, die Auswirkungen zu minimieren: Die Anwendung darf nur mit den niedrigsten möglichen Rechten auf die Datenbank zugreifen, nicht benötigte SQL-Funktionen müssen deaktiviert und bereitgestellte Patches müssen zeitnah installiert werden.

Damit ist das Thema "SQL-Injection" vorerst beendet. In der nächsten Folge geht es um die Suche nach Directory-Traversal-Schwachstellen.

Wenn Sie Fragen oder Themenvorschläge haben, können Sie diese gerne an die angegebene E-Mail-Adresse senden oder im Security-Forum einbringen!

Carsten Eilers

About Security - Übersicht zum aktuellen Thema:

Kommentare

Folgende Links könnten Sie auch interessieren