SQL-Injection im Schnelldurchlauf
Laut dem Cloud-Hosting-Anbieter FireHost ist die Zahl der erkannten SQL-Injection-Angriffe zwischen April und Juni 2012 um 69% gestiegen. Während im 1. Quartal 2012 "nur" 277.770 Angriffe abgewehrt wurden, waren es im 2. Quartal 469.983 Angriffe. Was ist da los?
Alles ist relativ...
Der Anstieg um 69% ist eindeutig bemerkenswert, aber wenn man sich die restlichen Werte in der Pressemitteilung von FireHost ansieht, relativiert sich das etwas:
- 43% aller Angriffe im 2. Quartal 2012 waren Directory-Traversal-Angriffe
- 27% aller Angriffe waren Cross-Site-Scripting-Angriffe (XSS)
- 21% aller Angriffe waren SQL-Injection-Angriffe, sie liegen also nur auf Platz 3 alle Angriffe und machen davon etwas mehr als 1/5 aus.
- 9% aller Angriffe waren Cross-Site-Request-Forgery-Angriffe (CSRF)
Vergleicht man das mit dem 1. Quartal, sieht es auch noch nicht bedrohlicher aus, der Anstieg wird aber deutlich:
1. Quartal | 2. Quartal |
---|---|
1. Cross-Site Scripting, 40% | 27%, Platz 2 |
2. Directory Traversal, 38% | 43%, Platz 1 |
3. Cross-Site Request Forgery, 12% | 9%, Platz 4 |
4. SQL-Injection, 10% | 21%, Platz 3 |
Was ist SQL-Injection?
Die Structured Query Language (SQL) ist eine Abfragesprache für relationale Datenbanken. Viele Webanwendungen verwenden zur Speicherung von Informationen eine solche Datenbank.
Unabhängig davon, ob es sich z.B. um die Einträge in einem Blog, die Artikel in einem Webshop, die Benutzerinformationen in einem Forum, die Texte in einem Content-Management-System oder was auch immer handelt, bieten die Webanwendungen meist eine oder mehrere Möglichkeiten für den Benutzer, um Daten aus der Datenbank zu lesen und/oder in die Datenbank einzutragen, was beides über eine sog. query, also eine Abfrage, geschieht.
Diese Abfragen werden intern in SQL formuliert. Dabei werden meist vorgegebene Teile mit den Benutzereingaben zu einer kompletten Abfrage kombiniert (eine bessere Lösung wird unten vorgestellt). Werden die vom Benutzer gelieferten Eingaben nicht ausreichend geprüft bzw. gefiltert, kann ein Angreifer beliebige SQL-Befehle in die Abfragen einschleusen. Dieses Einschleusen von Code wird als SQL Injection bezeichnet.
Beispiele für SQL-Injection
Mit diesen eingeschleusten Befehlen kann ein Angreifer ziemlich viel Unheil anrichten. Typische Beispiele sind das Ausspähen von Daten und das Umgehen der Authentifizierung, d.h. der Login-Funktion. Hier soll als Beispiel das Ausspähen von Daten dienen:
Eine Webanwendung, z.B. ein Forum, speichert die Benutzerinformationen in
der Tabelle Benutzertabelle
einer Datenbank. Die Tabelle hat Spalten
wie z.B. BenutzerID
, BenutzerName
,
RealName
, Ort
und einige mehr, z.B. für den
Rest der Anschrift, die Kreditkarten- oder Bankdaten für die Bezahlung
der Anwendung, das Passwort des Benutzers usw. usf.
Der SQL-Befehl
SELECT * FROM Benutzertabelle WHERE Ort = 'Berlin'
gibt alle Einträge aus der Tabelle Benutzer
aus, die in der
Spalte Ort
den Wert Berlin aufweisen.
Das ist schön, aber unflexibel. Besser wäre es, wenn die Benutzer den Ort frei wählen könnten. Entsprechend werden in Webanwendungen statt konstanter Werte i.A. Variablen verwendet, die mit vom Benutzer gelieferten Werten gefüllt werden:
SELECT * FROM Benutzertabelle WHERE Ort = '$ort'
Solange $ort
nur Eingaben wie Berlin, Hamburg, ... oder
allgemein Wörter enthält, passiert nichts Unerwünschtes.
Würde z.B. als Wert für $ort
das Wort
"Oberweserdampfschifffahrtkapitänsmütze" eingegeben,
würde einfach gar nichts zurück geliefert (sofern nicht irgend
ein Scherzbold behauptet hat, er wohne in
"Oberweserdampfschifffahrtkapitänsmütze"). Ein
Angreifer könnte aber als Ort SQL-Befehle eingeben, z.B.
' OR 1=1 --
Damit ergibt sich die SQL-Abfrage
SELECT * FROM Benutzertabelle WHERE Ort = '' OR 1=1 --'
Umgangssprachlich werden alle Einträgen ausgegeben, in denen die Spalte
Ort
leer ist oder (OR
) für die 1=1
ist. Und das sind alle Einträge, da 1=1
immer gilt. Die
--
markieren den Rest, also das '
der
vorbereiteten Abfrage, als Kommentar, der ignoriert wird.
Mit anderen Worte: Der Angreifer bekommt alle Daten geliefert, die in der Datenbank enthalten sind. Er hat dann also eine Liste, in der für jeden Benutzer dessen Zugangsdaten (Benutzername und Passwort), sein Realname, seine Anschrift und seine Kreditkartendaten oder Bankverbindung stehen. Und alles, was sonst noch in der entsprechenden Tabelle gespeichert ist.
Evtl. sind solche Angriffe für einige der seit einiger Zeit um sich greifenden Passwortlecks verantwortlich.
Weitere Beispiele für SQL-Injection-Angriffe finden Sie in den entsprechenden Folgen von About Security:
- About Security #11: SQL-Injection
- About Security #12: SQL-Injection verhindern
- About Security #13: Mit Stored Procedures gegen SQL-Injection
Drive-by-Infektion nach SQL-Injection
Außer dem Ausspähen von Daten und dem Umgehen der Authentifizierung gibt es einen weiteren inzwischen üblich gewordenen Angriff über SQL-Injection: Das Präparieren harmloser Websites für Drive-by-Infektionen. Einige Beispiele für solche Angriffe, die oft in Form von Massenhacks vor sich gehen, sind LizaMoon (der weitere Kreise zog als anfangs angenommen), urchin.js und lilupophilupop (der immer noch aktiv ist oder es zumindest im Mai noch war).
Aktuell
laufen Angriffe,
die wohl den Namen 'lasimp04risoned' bekommen werden, denn die
Angriffe werden i.A. nach dem Namen der für die Drive-by-Infektion
verwendeten Domains oder Skripte benannt, und bei diesem Angriff werden
die Opfer auf die Domain lasimp04risoned.rr.nu
geleitet.
Ansonsten folgt der Angriff dem schon bekannten Muster. Ob die
Cyberkriminellen dabei voneinander abschreiben oder ob es immer die
gleichen Angreifer sind, ist nicht bekannt.
SQL-Injection-Schwachstellen finden
Die Suche nach SQL-Injection-Schwachstellen ist nicht ganz trivial. Die
einfachsten Fälle finden Sie schon, wenn Sie in einen für eine
SQL-Abfrage genutzten Parameter ein '
einfügen und eine
SQL-Fehlermeldung erhalten. I.A. liegt dann was im Argen und SQL-Injection
ist möglich. Wie man auch anspruchsvollere Schwachstellen finden
kann, habe ich zumindest teilweise in den entsprechenden Folgen von About
Security beschrieben:
- About Security #166: Schwachstellen-Suche: SQL-Injection Grundlagen
- About Security #167: Schwachstellen-Suche: SQL-Injection über Strings
- About Security #168: Schwachstellen-Suche: SQL-Injection statt Zahlen
- About Security #169: Schwachstellen-Suche: SQL-Injection Statements
- About Security #170: Schwachstellen-Suche: SQL-Injection mit UNION
- About Security #171: Schwachstellen-Suche: SQL-Injection mit UNION (2)
- About Security #172: Schwachstellen-Suche: SQL-Injection mit Filter
- About Security #173: Schwachstellen-Suche: SQL-Injection mit Escape
- About Security #174: Schwachstellen-Suche: SQL-Injection 2. Ordnung
- About Security #175: Schwachstellen-Suche: Blind SQL-Injection
Falls Sie in Ihrer Webanwendung SQL-Injection-Schwachstellen finden, sollten Sie auch gleich noch nach allen anderen möglichen Schwachstellen suchen. I.A. gibt es dann immer noch ein paar andere, z.B. XSS oder CSRF oder Directory Traversal oder ...
Im Zweifelsfall ist es immer besser, Sie beauftragen jemanden mit der Schwachstellensuche, der sich damit auskennt. Zum Beispiel mich (diese Eigenwerbung muss jetzt sein).
SQL-Injection verhindern
Es gibt mehrere Möglichkeiten, SQL-Injection zu verhindern:
- Die Eingaben können auf Korrektheit geprüft werden, nur
Eingaben, die den erwarteten Format entsprechen, werden von der
Webanwendung verwendet.
So kann man z.B. eine E-Mail-Adresse auf Korrektheit prüfen oder numerische Eingaben in den passenden Wertebereich umwandeln. - Die Eingaben können maskiert werden, so dass potentiell
gefährliche Sonderzeichen unbrauchbar gemacht werden.
Z.B. gibt es in PHP die Funktionenaddslashes()
und speziell für MySQLmysql_real_escape_string()
zum Maskieren bestimmter Zeichen wie'
und\
. - Am Sichersten ist der Einsatz von Prepared Statements mit
parametrisierten Aufrufen.
Der Aufbau des SQL-Statements wird dabei in zwei Schritte aufgespalten:
- Die Struktur der Abfrage wird definiert, für alle Eingaben werden Platzhalter eingesetzt.
- Der Inhalt der Platzhalter wird spezifiziert.
Ein Problem aller Prüf- und Filtermethoden ist, dass die Funktionen unter Umständen durch andere Darstellungsformen für die zu filternden Zeichen (z.B. UTF, URL-Kodierung) ausgetrickst werden können. Ich rate daher dringend zum Einsatz von Prepared Statements mit parametrisierten Aufrufen.
Auch zur Verhinderung von SQL-Injection-Schwachstellen finden Sie weitere Informationen in den entsprechenden Folgen von About Security:
- About Security #12: SQL-Injection verhindern
- About Security #13: Mit Stored Procedures gegen SQL-Injection
- About Security #176: Schwachstellen-Suche: SQL-Injection verhindern
Nach diesem kurzen Ausflug zur SQL-Injection geht es in der nächsten Folge wie bereits angekündigt um den Einsatz des Google Hacking im Rahmen des Penetration Testings.
Trackbacks
Dipl.-Inform. Carsten Eilers am : Links mit etwas Senf
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Websecurity - Logikfehler vermeiden
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Drive-by-Infektionen über kompromittierte Webanwendungen
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Drucksache: Entwickler Magazin 2.2014 - Die OWASP Top 10, Teil 1
Vorschau anzeigen
entwickler.de am : PingBack
Die Anzeige des Inhaltes dieses Trackbacks ist leider nicht möglich.Dipl.-Inform. Carsten Eilers am : Drucksache: PHP Magazin 5.16 - Forschungsfeld Webanwendung
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Die IoT Top 10, #1: Unsichere Weboberflächen, Teil 1
Vorschau anzeigen
Dipl.-Inform. Carsten Eilers am : Der SDL am Beispiel eines Gästebuchs, Teil 6
Vorschau anzeigen