SQL Injections in Webanwendungen Maximilian Geissler Betreuer: Daniel Raumer Seminar Network Hacking WS2013 Lehrstuhl Netzarchitekturen und Netzdienste Fakultät für Informatik, Technische Universität München Email: [email protected] KURZFASSUNG 3. Die meisten Webanwendungen sind verwundbar gegenüber SQL Injections. Dieses Paper gibt einen Überblick über SQL Injections und Gegenmaßnahmen. Dazu wird die Funktionsweise von SQL Injections erläutert. Auf die im Bereich der HTTP Webanwendungen häufig anzutreffende Kombination PHP und MySQL wird besonders eingegangen. Durch die vorgestellten Prinzipien können typische Fehler bei der Entwicklung von Webanwendungen vermieden und SQL Injections verhindert werden. Es gibt unterschiedliche Motivationen für einen Angreifer, eine SQL Injection durchzuführen. In dieser Arbeit werden diese folgendermaßen klassifiziert: Schlüsselworte Manipulation von Daten Durch das Hinzufügen, Veränderen oder Löschen von Daten kann ein Angreifer eine Anwendung manipulieren. Beispielsweise könnte er in einem Webshop den Preis für eine bestimmte Ware verändern. SQL Injection, SQLIA, SQLIV, Webanwendung 1. EINFÜHRUNG SQL Injections sind eine weit verbreitete Methode, Anwendungen anzugreifen. Die meisten Webanwendungen [1] und auch lokale Anwendungen, die auf einer SQL-Datenbank aufbauen, sind davon betroffen. Datenbanken sind ein beliebtes Angriffsziel, da darin wertvolle Inhalte, wie z.B. Kundendaten einer Firma, verwaltet werden. Es existieren sehr viele Webanwendungen, die gegenüber SQL Injections verwundbar sind [2]. Aus diesen Gründen sind SQL Injections weit verbreitet. Laut dem Application Vulnerability Trends Re” port 2013“ [3] der Cenzic, Inc waren durchschnittlich 6% aller getesteten Anwendungen verwundbar gegenüber SQL Injections. Das OWASP Top Ten Project [4] stuft für das Jahr 2013 SQL Injections als die größte Gefahr für Webanwendungen ein [5]. Im folgenden Abschnitt 2 wird die Definition einer SQL Injection angegeben und in Abschnitt 3 werden die Ziele eines Angriffs vorgestellt. Anschließend werden in Abschnitt 4 die Angriffspunkte als Basis für die Durchführung einer SQL Injection (Abschnitt 5) aufgezeigt. In Abschnitt 6 werden Maßnahmen gegen SQL Injections vorgestellt. 2. DEFINITION EINER SQL INJECTION SQL Injection bezeichnet einen Angriff, auch SQL injection attack (SQLIA) genannt, auf datenbankbasierende Anwendungen durch spezielle Benutzereingaben. Diese Benutzereingaben werden aufgrund mangelhafter Überprüfung akzeptiert und erlauben dem Angreifer, Daten zu manipulieren oder die Anwendung anderweitig zu kompromittieren [6]. Die Vorraussetzung einer SQL Injection ist eine SQLIV (SQL injection vulnerability), also eine Sicherheitslücke oder Schwachstelle in einer Anwendung. ZIELE VON SQL INJECTIONS Kopieren von Daten Das gängigste Ziel einer SQL Injection ist es, Daten, die nicht öffentlich verfügbar sind, einzusehen und zu kopieren [7]. Der Angreifer verschafft sich so wertvolle Informationen. Denial of Service (DoS) Bei einem Denial of Service ist die Anwendung für Benutzer nicht mehr verfügbar. Die Motivation hinter einer DoS Attacke können wirtschaftliche Interessen oder Konkurrenzkämpfe sein. Umgehen von Authentifizierungen Angreifer können sich durch SQL Injections Zugriff auf Funktionen von Anwendungen verschaffen, die durch Authentifizierungen geschützt sind. Einschleusen von Code Wenn ein Angreifer in ein System eingedrungen ist, kann er schädlichen Code einschleusen1 , den er später ausführen kann. Oft verfolgen Angreifer nicht nur eines sondern mehrere dieser Ziele. 4. ANGRIFFSPUNKTE Die typischen Angriffspunkte bei datenbankbasierten Webanwendungen, die mittels HTTP mit dem Server kommunizieren, sind: Benutzereingaben Benutzereingaben können in Webanwendungen unter Verwendung von HTML Formularen an die Anwendung übermittelt werden. Durch den Missbrauch dieser Formulare wird eine SQL Injection möglich. Dabei wird ein spezieller Text in ein Feld des Formulares 1 Beispielsweise mit Stored Procedures [8]. 5.1.1 Angriffspunkte finden Zunächst müssen Angriffspunkte, wie in Abschnitt 4 beschrieben, gefunden werden. Sie bilden die Basis für die weiteren Schritte. 5.1.2 Fingerprinting Verschiedene Datenbanksysteme reagieren leicht unterschiedlich auf bestimmte Eingaben. Fehlerhafte Eingaben können zu Fehlermeldungen führen, die viele Informationen verraten (siehe auch Abschnitt 5.2.2). Falls es gelingt, durch dieses Fingerprinting auf Typ und Version zu schließen, kann ein gezielter Angriff auf dieses Datenbanksystem durchgeführt werden [10]. Abbildung 1: Missbrauch von Formularen eingegeben, wie in Abbildung 1 dargestellt. Wenn die Clientsoftware auf HTML und Scriptsprachen wie Javascript aufbaut, liegt sie nicht in kompilierter Form, sondern als Quelltext vor. Somit ist sie leicht zu verändern. Einige Browser bieten die Möglichkeit, mit Hilfe von Developer Tools den HTML Code einer Webseite direkt zu verändern und somit Validierungen, die in Skriptsprachen implementiert sind, zu umgehen. Beispielsweise bietet der Browser Firefox eine solche Funktion im Menü unter Tools/Web Developer/Inspector. HTTP Header Eine weitere Möglichkeit, eine Webanwendung anzugreifen, sind HTTP Header. Wenn die Daten dieser Header in Datenbankabfragen verwendet werden, kann durch veränderte Header eine SQL Injection durchgeführt werden. Cookies Cookies sind ein wichtiger Angriffspunkt für Webanwendungen. Da sie auf Seite des Clients gespeichert sind, ist eine Manipulation möglich. Cookies werden als HTTP Header übertragen und somit gilt für sie die selbe Missbrauchsmöglichkeit wie für HTTP Header. Parameter Mithilfe der Methoden GET und POST können in Webanwendungen Parameter in Form von Key-ValuePaaren an den Server übergeben werden. Diese Parameter können auf der Clientseite beliebig gesetzt werden. Für GET wird eine angepasste URL aufgerufen und für POST wird ein modifizierter HTTP Request abgesetzt. 5. DURCHFÜHRUNG EINER SQLIA In diesem Kapitel wird vorgestellt, wie ein Angriff vorbereitet werden kann und welche Angriffsarten möglich ist. 5.1 Angriffsvorbereitung Um einen erfolgreichen und präzisen Angriff durchzuführen, ist es hilfreich, Informationen über die Anwendung und deren Datenbank zu sammeln. Im Folgenden wird ein kurzer Überblick über Techniken zum Erlangen dieser Informationen gegeben. 5.1.3 Datenbankschemata herausfinden Kenntnisse über die Datenbankschemata werden gebraucht für eine SQL Injection. Informationen wie Tabellennamen und Spaltennamen sind nötig, um Datenbankabfragen zu erstellen, die die gesuchten Daten liefern [11]. 5.1.4 Rechte erlangen Wenn bestimmte Daten im Datenbanksystem durch besonders hohe Zugriffsrechte geschützt sind, kann ein Angreifer versuchen, sich durch einen vorausgehenden Angriff höhere Benutzerrechte zu verschaffen. 5.2 Angriffsarten In diesem Abschnitt werden unterschiedliche Angriffsarten vorgestellt, die in einer SQLIA genutzt werden können. Viele der Angriffe haben gemeinsam, dass in den SQL Abfragen mithilfe von Kommentarzeichen, wie z.B. - -“, Teile der ” Abfrage für den SQL Interpreter unsichtbar gemacht werden [12]. 5.2.1 Tautologien Bei dieser Art von Attacke wird eine SQL Abfrage mit einer WHERE Bedingung ausgenutzt. Die WHERE Bedingung wird durch geschicktes Anpassen der Eingabe zu einer Tautologie umgebaut [7]. Ein typischer Anwendungsfall ist das Umgehen von Authentifizierungen. Eine mögliche SQL Abfrage für das Formular aus Abbildung 1 ist in Listing 1 zu sehen. Dabei werden die Platzhalter $u und $p durch den Inhalt der Felder Username bzw. Password des Formulares ersetzt. Listing 1: SQL Abfrage s e l e c t ∗ from u s e r s where username = ’ $u ’ and password = ’ $p ’ Listing 2: SQL Injection hi ’ o r 1=1 −− Wird nun statt einem Benutzernamen eine SQL Injection wie in Listing 2 angegeben, ist die WHERE Bedingung der SQL Abfrage in eine Tautologie umgebaut worden (Listing 3). Listing 3: Modifizierte SQL Abfrage s e l e c t ∗ from u s e r s where username = ’ h i ’ or 1=1 −− ’ and password = ’ t e x t ’ Das ist möglich durch das geschickte Verwenden der Steuerzeichen - -“, die den SQL Interpreter anweisen, den letzten ” Teil der Abfrage als Kommentar zu interpretieren und folglich zu ignorieren (In Listing 3 kursiv dargestellt). Somit liefert die resultierende SQL Abfrage alle Datensätze der Tabelle users ohne Authentifizierung. 5.2.2 Ungültige Abfragen Datenbanksysteme geben bei ungültigen SQL Abfragen Fehlermeldungen zurück, falls diese Funktion nicht deaktiviert wurde. Wenn diese Fehlermeldungen dem Benutzer in der Webanwendung angezeigt werden, können durch sie Informationen über das Datenbanksystem und die Datenbankstrukturen gesammelt werden. Diese Attacke dient vor allem der Angriffsvorbereitung, weil mit Hilfe der neu gewonnenen Informationen präzisere Angriffe möglich werden. Listing 4: SQL Abfrage s e l e c t ∗ from s t u d e n t s where name = ’ $n ’ Listing 5: Modifizierte SQL Abfrage s e l e c t ∗ from s t u d e n t s where name = ’ Die SQL Abfrage in Listing 4 wird durch die SQL Injection -- im Platzhalter $n zu einer ungültigen SQL Abfrage (Listing 5). Diese ungültige SQL Abfrage führt beispielsweise zu folgender Fehlermeldung: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ” at line 1 Wenn die Fehlermeldung in der Webanwendung angezeigt wird, ist dem Angreifer nun bekannt, dass die Webanwendung MySQL als Datenbanksystem verwendet. Damit sind ihm künftig gezielte Angriffe auf dieses Datenbanksystem möglich. Der Angreifer hat somit erfolgreich Fingerprinting (Abschnitt 5.1.2) betrieben. Auch über Datenbankstrukturen können Informationen gesammelt werden. Wenn der Name der Benutzertabelle nicht bekannt ist, kann ein Angreifer gängige Tabellennamen wie users, user, accounts usw. durchprobieren. MySQL würde z.B. Fehlermeldungen wie Table ’database.users’ doesn’t exist liefern. Der Angreifer wiederholt seine Attacke mit anderen Tabellennamen solange, bis der Fehler nicht mehr auftritt. Dann ist ihm der richtige Tabellenname bekannt. Die gleiche Vorgehensweise kann auch für unbekannte Spaltennamen in Tabellen verwendet werden. 5.2.3 Union Queries Mithilfe von UNION können in SQL die Ergebnisse mehrerer Abfragen zusammengefasst werden. Auf dieser Basis werden Union Query Angriffe durchgeführt. Listing 6: SQL Abfrage s e l e c t s e m e s t e r from s t u d e n t s where name = ’ $n ’ Listing 7: SQL Injection ’ union s e l e c t accountNumber from bankAccounts where u s e r i d = 42 −− Der Platzhalter $n in Listing 6 wird ersetzt durch die SQL Injection in Listing 7. Das Resultat ist dargestellt in Listing 8. Listing 8: Modifizierte SQL Abfrage s e l e c t s e m e s t e r from s t u d e n t s where name = ’ ’ union s e l e c t accountNumber from bankAccounts where u s e r i d = 42 −− ’ Unter der Annahme, dass es keinen Studenten mit leerem Namen gibt, wird die Bedingung der ersten SELECT Abfrage nie erfüllt. Folglich liefert die erste Abfrage NULL. Die zweite Abfrage liefert die Spalte accountNumber aus der Tabelle bankAccounts für den Benutzer mit der ID 42. Die ID wird zuvor in Erfahrung gebracht oder zufällig gewählt. Durch UNION wird als Ergebnis nur eine Zeile mit der Spalte accountNumber zurückgegeben. Die Webanwendung wird dem Benutzer diesen Wert unter der Annahme, es handle sich um die Spalte semester der Tabelle students, anzeigen. Auf diese Art und Weise können Daten anderer Tabellen aus der Datenbank extrahiert werden. 5.2.4 Piggy-Backed Queries Die Möglichkeit, mehrere Abfragen durch spezielle Delimeter2 zu trennen und somit mehrere Abfragen hintereinander auszuführen, kann für eine Attacke verwendet werden. Diese Art der Attacke wird Piggy-Backed Query genannt [13]. Bei dieser Attacke wird nicht die eigentliche Abfrage (Listing 9) geändert sondern eine neue Abfrage hinzugefügt [13]. Dadurch kann beliebiger SQL Code auf der Datenbank ausgeführt werden. Listing 9: SQL Abfrage s e l e c t ∗ from s t u d e n t s where name = ’ $n ’ Wenn der Platzhalter $n durch die SQL Injection (Listing 10) ersetzt wird, ist es möglich, die gesamten Benutzertabelle zu löschen (Listing 11). Listing 10: SQL Injection Robert ’ ; drop t a b l e s t u d e n t s −− Listing 11: Piggy-Backed Query s e l e c t ∗ from s t u d e n t s where name = ’ Robert ’ ; drop table s t u d e n t s −− ’ 2 In vielen SQL Datenbanksystemen wird das Symbol ; standardmäßig als Delimeter verwendet, z.B. in MySQL. 5.2.5 Stored Procedures Stored Procedures sind Funktionen in Datenbanksystemen. Viele Datenbanksysteme enthalten fertige Stored Procedures oder bieten die Möglichkeit, diese zu erstellen [8, 14]. Häufig wird fälschlicherweise angenommen, dass Stored Procedures Schutz vor SQL Injections bieten, doch sie sind ebenfalls angreifbar [7]. Wei stellt in [15] Methoden vor, wie Attacken mit Hilfe von Stored Procedures funktionieren und verhindert werden können. 5.2.6 Inferences Wenn keine verwertbaren Informationen wie Fehlermeldungen der Datenbank an den Benutzer der Anwendung weitergeleitet werden, muss das Feedback auf eine andere Art und Weise eingeholt werden. Blind SQL Injection Bei dieser Technik wird auf Informationen geschlossen. Zum Beispiel war eine SQL Injection wie 100 and 1=1 auf einer ID wahrscheinlich erfolgreich, wenn die Webseite genau den selben Inhalt anzeigt wie wenn 100 übergeben wird. Eine detaillierte Beschreibung wie Blind SQL Injections funktionieren, stellt Spett in [16] vor. Timing SQL Injection Wenn absolut keine verwertbaren Informationen erlangt werden können, ist die einzige Möglichkeit eine Timing SQL Injection. Dabei wird die Zeit, die eine SQL Abfrage braucht gemessen und dazu benutzt Rückschlüsse auf den Erfolg der Injection zu ziehen. Timing SQL Injections werden in [7, 17] detailliert behandelt. 5.3 Beispiel für einen Angriff Nachfolgend wird ein Beispiel für eine SQLIA in PHP und MySQL vorgestellt. 1 2 3 Listing 12: SQLIV in PHP $username = $ GET [ ”username ” ] ; $query = ” s e l e c t ∗ from u s e r s where username = ’ ” . $username . ” ’ ” ; $ r e s u l t = m y s q l i q u e r y ( $con , $query ) ; In Listing 12 wird in einem (unvollständig dargestellten) PHP Skript eine SQL Abfrage an eine MySQL Datenbank gesendet. Die Abfrage wird dynamisch generiert und hängt von dem per HTTP GET übergebenen Parameter username ab. Die fehlende Eingabeüberprüfung in diesem Beispiel ist eine gravierende Schwachstelle, die für eine SQL Injection genutzt werden kann und somit eine SQLIV darstellt. Durch den Aufruf der URL dieses PHP Skripts kann die SQLIA durchgeführt werden (Listing 13). Dabei muss die SQL Injection in URL encoding [18] übergeben werden, damit alle Sonderzeichen korrekt an das Skript übertragen werden. Listing 13: SQL Injection durch URL http :// www . example . com / script . php ? username = Robert %27%3 B %20 drop %20 table %20 users %3 B %20 - -%20 Der Angriff in Listing 13 verwendet die Angriffsart PiggyBacked Query und basiert auf der SQL Injection aus Listing 10. Dem Angreifer ist es möglich, durch den Aufruf der URL die Tabelle users zu löschen. 6. GEGENMAßNAHMEN Im Folgenden werden drei mögliche Gegenmaßnahmen vorgestellt: Defensives Programmieren, Zugriffsbeschränkungen im DBMS und automatisierte Schwachstellenerkennung. 6.1 Defensives Programmieren Das Absichern einer Anwendung gegen SQL Injections beginnt idealerweise bereits beim Erstellen der Anwendung. Durch Defensives Programmieren werden SQLIVs bereits während der Entwicklung vermieden. Da eine zeit- und kostenaufwändige Nachbesserung der Anwendung vermieden wird, sollte Defensives Programmieren stets betrieben werden, insbesondere bei Neuentwicklungen. Eine große Hilfe für Programmierer stellt das OWASP SQL Injection Prevention Cheat Sheet [2] dar. In diesem Dokument werden Methoden und Programmierpraktiken vorgestellt, die SQL Injections effektiv verhindern können. Das Grundprinzip des Defensiven Programmierens ist All Input Is Evil!“ [9]. Dement” sprechend sollten alle Eingaben der Anwendung, insbesondere Benutzereingaben, als potentielle Angriffspunkte gesehen werden. 6.1.1 Escaping Escaping ist eine Technik, Eingaben so zu verändern, dass SQL Steuerzeichen, wie ’ oder ; vom SQL Interpreter ignoriert bzw. als Teil der Zeichenkette betrachtet werden. Escaping ist eine weit verbreitete Methode, um SQL Injections zu verhindern. Listing 14 zeigt, wie durch das Voranstellen des Escaping Symbols \ das Steuerzeichen ’ als Teil der Zeichenkette Scarlett O’Hara interpretiert wird und somit die Struktur der SQL Abfrage durch die Zeichenkette nicht verändert wird. Listing 14: Beispiel für Escaping s e l e c t ∗ from u s e r s where name = ’ S c a r l e t t O\ ’ Hara ’ Durch Programmiersprachen und Anwendungsframeworks, die Methoden für automatisches Escaping anbieten, kann dem Programmierer die Arbeit erleichtert werden. Nachfolgend wird eine Auswahl von Escaping Methoden in PHP vorgestellt. magic quotes gpc Wenn diese PHP Einstellung gesetzt ist, werden Eingaben, die dem Skript als Parameter übergeben werden (z.B. per GET), automatisch durch Escaping Funktionen behandelt. Diese Einstellung sollte aber nicht verwendet werden, da sie keinen vollständigen Schutz vor SQL Injections bietet [19]. addslashes(...) Diese Funktion wird zwar häufig für Escaping verwendet, bietet aber nicht unbedingt Schutz vor SQL Injections, da sie nicht alle Möglichkeiten von Injections abdeckt [20]. Eine bessere Alternative sind datenbankspezifische Escaping Funktionen. mysql real escape string(...) Diese MySQL spezifische Funktion bietet den besten Schutz, falls MySQL verwendet wird. Dennoch gibt es Exploits [21]. Viele Escaping Techniken können durch Alternate Encodings [7] umgangen werden. Somit bietet Escaping keinen vollständigen Schutz vor SQL Injections. Daher sollten sich Anwendungen nicht nur auf Escaping verlassen, sondern weitere Schutzmaßnahmen anwenden. 6.1.2 Datentypsicherheit Durch die Überprüfung des Datentyps werden ebenfalls viele SQL Injections vermieden, weil Steuerzeichen nicht bis zum SQL Interpreter gelangen können. 1 2 3 4 Listing 15: Beispiel für Datentypsicherheit $ i = $ GET [ ” u s e r i d ” ] ; $ i = intval ( $ i ) ; $query = ” s e l e c t ∗ from u s e r s where i d = ”. $i ; $ r e s u l t = m y s q l i q u e r y ( $con , $query ) ; In einer SQL Abfrage wie in Listing 15 wird die ID des Benutzers in der Where-Bedingung überprüft. Wenn bekannt ist, welcher Datentyp das Feld id hat (hier z.B. Integer), kann die Eingabe für den Platzhalter $i vorher in einen Integer umgewandelt werden (Zeile 2). An dieser Stelle wird nun eine SQL Injection verhindert. Diese Technik funktioniert sehr gut bei numerischen Datentypen. Aufwändiger wird es bei Datums- und Zeittypen und vor allem bei String-Typen, also Zeichenketten. Bei diesen Datentypen bietet es sich an, White List Input Validation anzuwenden. 6.1.3 White List Input Validation Bei White List Input Validation [22] werden nur bestimmte Zeichen in der Eingabe zugelassen (whitelisting). Eine Realisierung ist z.B. mit Regular Expressions möglich. Listing 16: Beispiel für White List Input Validation 1 $p = $ GET [ ”phone ” ] ; 2 i f ( ! preg match ( ”/ ˆ ( [ 0 − 9 ] | − ) ∗ $ / i ” , $p ) ) 3 { 4 e x i t ( ” I n v a l i d phone number ”) ; 5 } 6 $query = ” s e l e c t name from u s e r s where phone = ” . $p ; 7 $ r e s u l t = m y s q l i q u e r y ( $con , $query ) ; Listing 16 zeigt ein Beispiel in PHP. Die White List Input Validation in Zeile 2 erlaubt nur bestimmte Arten von Zeichenketten, hier Telefonnummern. In Telefonnummern sind in diesem Beispiel nur Ziffern und das Symbol - erlaubt. Wenn ein anderes Zeichen in der Zeichenkette vorhanden ist, wird das Programm abgebrochen. 6.1.4 Eigene Fehlerausgabe Eine wichtige Gegenmaßnahme ist, Fehlermeldungen sehr knapp zu halten bzw. nicht direkt an die Benutzer der Anwendung weiterzugeben. Das verringert das Risiko einer SQL Injection stark, weil dem Angreifer die Angriffsvorbereitung (Abschnitt 5.1), insbesondere Fingerprinting und das Herausfinden von Datenbankschemata, erschwert wird. Die Angriffsart Ungültige Abfragen (Abschnitt 5.2.2) ist dann nicht möglich, weil sie auf detaillierten Fehlermeldungen aufbaut. Deswegen ist es von Vorteil, in eine Anwendung eine Einstellung einzubauen, die definiert ob die Anwendung im Debugbzw. Entwicklungsmodus läuft. Wenn diese Einstellung aktiviert ist, werden detaillierte Fehler ausgegeben, die die Entwickler in ihrer Tätigkeit bestmöglich unterstützen. Wenn die Anwendung fertig entwickelt ist, wird diese Einstellung deaktiviert und es werden nur noch allgemeine Fehlermeldungen, wie z.B. Datenbankfehler“, zurückgegeben. ” 6.1.5 Prepared Statements Prepared Statements, auch Parameterized Queries genannt, sind die sicherste Maßnahme gegen SQL Injections und sollten von allen Entwicklern verwendet werden [2]. Bei Prepared Statements muss der Entwickler erst die Struktur der SQL Abfrage definieren und danach die Daten, die in die Struktur eingesetzt werden. Durch die Trennung von Struktur und Daten ist keine Veränderung der Struktur durch manipulierte Daten mehr möglich und somit werden SQL Injections effektiv verhindert. 1 2 3 4 5 6 7 8 9 10 11 12 13 Listing 17: Beispiel für Prepared Statements /∗ I n i t i a l i z e d a t a b a s e c o n n e c t i o n ∗/ $ m y s q l i = new m y s q l i ( ” l o c a l h o s t ” , ” u s e r ” , ”password ” , ”db ”) ; /∗ C r e a t e Prepared S t a t e m e n t ∗/ $stmt = $mysqli −>p r e p a r e ( ” s e l e c t ∗ from u s e r s where name = ? and p i n = ? ”) /∗ Bind p a r a m e t e r s ∗/ $name = $ GET [ ”name ” ] $ p i n = $ GET [ ”p i n ” ] $stmt−>bind param ( ” s i ” , $name , $ p i n ) ; /∗ E x e c u t e s t a t e m e n t ∗/ $stmt−>e x e c u t e ( ) ; In Listing 17 wird ein PHP Beispiel für eine SQL Abfrage unter Verwendung von Prepared Statements gezeigt. Dieses Minimalbeispiel soll nur das Prinzip verdeutlichen und verzichtet deswegen auf Fehlerbehandlung. In Zeile 5 wird das Prepared Statement erstellt. Hier ist darauf zu achten, dass keine Eingaben direkt in den Query-String eingebaut werden, sondern stattdessen als Platzhalter das Symbol ? verwendet wird. Die Platzhalter werden in Zeile 10 beim sogenannten bind -Vorgang durch Werte ersetzt. Dabei werden auch die Datentypen festgelegt: si bedeutet, dass zwei Platzhalter ersetzt werden, der erste vom Typ String (s) und der zweite vom Typ Integer (i). Durch den bind -Vorgang ist also automatisch Datentypsicherheit gegeben. Bei Prepared Statements muss kein gesondertes Escaping betrieben werden, da im bind -Vorgang die Struktur der SQL Abfrage nicht mehr verändert werden kann. Nach Zeile 10 kann das Prepared Statement $stmt verwendet werden, um sichere SQL Abfragen durchzuführen. 6.2 Zugriffsbeschränkungen im DBMS Das Datenbanksystem (auch DBMS, Datenbankmanagementsystem) muss durch Zugriffskontrollen abgesichert sein. Die Datenbankverbindung zwischen einer Anwendung und dem SQL Server kann durch die Verwendung von Benutzername und Passwort geschützt werden. Zwei verschiedene Datenbanken auf einem Server dürfen sich niemals Benutzername und Passwort teilen, weil sonst bei einem Bekanntwerden der Zugangsdaten mehrere Datenbanken auf einmal betroffen sind. Außerdem darf der Benutzer root niemals für Datenbankverbindungen in Anwendungen verwendet werden, da in der Standardeinstellung zu viele Rechte an diesen Benutzer vergeben sind. SQL Datenbanken wie MySQL erlauben sehr gezieltes Setzen von Rechten für Datenbankbenutzer [23]. Es gilt der Grundsatz: So viele Rechte wie nötig, aber so wenig wie möglich vergeben. Wird in einer Anwendung beispielsweise niemals ein DROP ausgeführt, sollten auch keine DROP Rechte an den Datenbankbenutzer, der in der Anwendung verwendet wird, vergeben sein. Es empfiehlt sich außerdem, vor allem bei großen Anwendungen, in unterschiedlichen Teilen der Anwendung verschiedene Datenbankbenutzer zu verwenden, die jeweils so wenig Rechte wie möglich haben. Wenn eine Attacke erfolgreich ist, kann der Angreifer nur in diesem Teil der Anwendung agieren und hat keinen oder nur eingeschränkten Zugriff auf andere Teile der Datenbank. 6.3 Automatisierte Schwachstellenerkennung Es gibt Tools, die automatisiert Schwachstellen in Anwendungen finden und oft auch automatisiert beheben können. Dieser Abschnitt bietet einen Überblick über dieses Thema sowie weiterführende Literatur dazu. 6.3.1 Codeanalysetools Tools in dieser Kategorie analysieren den Code der Anwendung, um Schwachstellen zu finden. Eine Möglichkeit ist beispielsweise der PSR-Generator Algorithmus (Prepared Statement Replacement Generator Algorithmus) [24], der alle dynamischen SQL Abfragen durch Prepared Statements ersetzt. In [25, 26, 24] werden Codeanalysetools näher besprochen. 6.3.2 Laufzeitanalysetools Tools dieser Art versuchen eine laufende Anwendung automatisiert mit gängigen Attacken anzugreifen. Der Code der Anwendung muss dem Tool nicht bekannt sein. Anschließend werden gefundene Sicherheitslücken angezeigt und der Entwickler kann seinen Code verbessern. Diese Tools können jedoch auch zur Angriffsvorbereitung missbraucht werden. Halfond, Viegas und Orso behandeln in [26] Laufzeitanalysetools. Es existiert eine weitere Art von Laufzeitanalysetools, die ständig zusammen mit der Anwendung auf dem Server laufen. Sie können z.B. durch Bibliotheken oder Middlewares (zwischen Anwendung und Datenbanksystem) den Verkehr zwischen Anwendung und SQL Server überwachen und versuchen Attacken zu erkennen und zu verhindern (intrusion detection) [27, 26]. Diese Systeme führen allerdings einen Overhead ein, weil sie permanent laufen müssen. 7. ZUSAMMENFASSUNG SQL Injections sind nach wie vor eine große Bedrohung für Anwendungen. Wenn aber die im Paper vorgestellten Prinzipien beachtet werden, können die meisten SQL Injections verhindert werden. Die wichtigste Gegenmaßnahme ist die Verwendung von Prepared Statements, weil nur mit dieser Technik Struktur und Daten einer SQL Abfrage getrennt werden. Dadurch werden SQL Injections nahezu unmöglich gemacht. Zusätzlich muss immer darauf geachtet werden, dass die Eingaben ausreichend überprüft werden, vor allem durch Datentypüberprüfung und White List Input Validation. Escaping sollte für alle Benutzereingaben durchgeführt werden, aber nicht als alleinige Maßnahme eingesetzt werden. Wenn die Datenbankbenutzer nur minimale Rechte haben, wird im Fall eines erfolgreichen Angriffs der Schaden begrenzt. Wenn all diese Empfehlungen umgesetzt werden, wird der Code einer Anwendung sehr viel sicherer und nahezu unverwundbar gegenüber SQL Injections. 8. LITERATUR [1] M. Shema: Seven Deadliest Web Application Attacks, Syngress, 2010 [2] SQL Injection Prevention Cheat Sheet, https://www.owasp.org/index.php/ SQL_Injection_Prevention_Cheat_Sheet (Zugriffsdatum: 22.12.2013) [3] Cenzic Inc.: Application Vulnerability Trends Report 2013, https://info.cenzic.com/2013-ApplicationSecurity-Trends-Report.html (Zugriffsdatum: 22.12.2013) [4] Open Web Application Security Project (OWASP), https://www.owasp.org/ (Zugriffsdatum: 22.12.2013) [5] OWASP Top 10 2013, https://www.owasp.org/index.php/Top_10_2013Top_10 (Zugriffsdatum: 22.12.2013) [6] Eckert: IT-Sicherheit, Kapitel 3.5.3, Oldenbourg Verlag, 2012 [7] William G.J. Halfond, Jeremy Viegas, Alessandro Orso: A Classification of SQL Injection Attacks and Countermeasures, IEEE International Symposium on Secure Software Engineering (ISSSE), 2006 [8] MySQL create procedure and create function Syntax, http://dev.mysql.com/doc/refman/5.5/en/createprocedure.html (Zugriffsdatum: 22.12.2013) [9] Michael Howard, David LeBlanc: Writing Source Code, Second Edition, Chapter 10: All Input Is Evil!“, ” Microsoft Press, 2004 [10] William G.J. Halfond, Jeremy Viegas, Alessandro Orso: A Classification of SQL Injection Attacks and Countermeasures, Proceedings of the IEEE International Symposium on Secure Software [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] Engineering, Kapitel 2.2, Performing database ” finger-printing“, 2006 William G.J. Halfond, Jeremy Viegas, Alessandro Orso: A Classification of SQL Injection Attacks and Countermeasures, Proceedings of the IEEE International Symposium on Secure Software Engineering, Kapitel 2.2, Determining database ” schema“, 2006 MySQL Kommentare, http://dev.mysql.com/doc/refman/5.1/de/ comments.html (Zugriffsdatum: 22.12.2013) Neha Mishra, Sunita Gond: Defenses To Protect Against SQL Injection Attacks, IJARCCE, 2013 Michael Howard, David LeBlanc: Writing Source Code, Second Edition, Microsoft Press, 2004 Ke Wei, Muthusrinivasan Muthuprasanna, Suraj Kothari: Preventing SQL injection attacks in stored procedures., Software Engineering Conference 2006, IEEE, 2006 Kevin Spett: Blind sql injection., SPI Dynamics Inc, Firmeninternes Paper, 2003 Ferruh Mavituna: Deep Blind SQL Injection., White Paper, 2008 Uniform Resource Identifier (URI): Generic Syntax, http://tools.ietf.org/html/rfc3986 (Zugriffsdatum: 22.12.2013) PHP: Why not to use Magic Quotes, http://www.php.net/manual/en/ security.magicquotes.whynot.php (Zugriffsdatum: 22.12.2013) PHP: addslashes, http://de3.php.net/addslashes (Zugriffsdatum: 22.12.2013) Get around mysql real escape string(), http://stackoverflow.com/a/12118602/2013757 (Zugriffsdatum: 22.12.2013) Input Validation Cheat Sheet, https://www.owasp.org/index.php/ Input_Validation_Cheat_Sheet (Zugriffsdatum: 22.12.2013) Kemper, Eickler: Datenbanksysteme, Kapitel 12.2, Oldenbourg Verlag, 2009 Sayyed Mohammad Sadegh Sajjadi, Bahare Tajalli Pour: Defenses To Protect Against SQL Injection Attacks, IJCCE, Vol. 2 No. 5, 2013 Lwin Khin Shar and Hee Beng Kuan Tan: Defeating SQL Injection, Nanyang Technological University, IEEE, 2013 William G.J. Halfond, Jeremy Viegas, Alessandro Orso: A Classification of SQL Injection Attacks and Countermeasures, IEEE International Symposium on Secure Software Engineering (ISSSE), Kapitel 5.2, Detection and Prevention Techniques“, 2006 ” Frank S. Rietta: Application layer intrusion detection for SQL injection., Proceedings of the 44th annual Southeast regional conference, ACM, 2006