SQL-Injektion - Einblicke und Gegenmaßnahmen
Immer häufiger entstehen Schwachstellen in Web-Applikationen, weil die Entwickler versäumen Ihre Software gegen die Manipulation von außen durch entsprechende Techniken abzusichern. Eine häufig benutze Angriffsmethode stellt dabei die so genannte SQL-Injektion dar.
Mit der entsprechenden Sorgfalt und auch einem gewissen Mehraufwand ist man allerdings hat man als Entwickler allerdings durchaus die Möglichkeit sich bzw. Seine Anwendung gegen SQL-Injektion zu schützen.
Wie SQL-Injektion funktioniert
Bei der SQL-Injektion werden Benutzer eingaben unzureichend oder gar ungefiltert in eine Datenbankabfrage verkettet. Dabei verwendet der Angreifer Zeichenketten, die von einem SQL-Server als Anweisung verstanden werden können. Für ihn ist es dabei von Vorteil, wenn er möglichst viel über die Interne Datenbank-Stuktur der jeweiligen Applikation kennt. OpenSource-Projekte, sind aus diesem Grund besonders anfällig für diese Art des Angriffs. Prinzipiell sind alle Programmiersprachen, die als Backend hinter der Web-Applikation stehen verwundbar. Allerdings gibt es bei einigen Sprachen Mechanismen, die verhindern sollen, dass es zu SQL-Injektionen kommen kann. Mit ein wenig Sorgfalt kann man aber in nahezu jeder Programmiersprache die Möglichkeit für eine potenzielle SQL-Injektion minimieren.
Beispiel für SQL-Injektion in PHP
Angenommen ein PHP-Programmierer möchte einen Datensatz aus einer SQL-Basierten Datenbank abfragen:
Die ID möchte er nun via GET-String übertragen:
http://www.meinhost.com/kunde/?id=1
SELECT * FROM user WHERE ID = {$_GET['id']}
Solange tatsächlich die ID im GET-String übertragen wird funktioniert alles bestens. Weiß der Angreifer aber etwas mehr über die Datenbank-Struktur, weiss er z.B. auch, dass es in der Tabelle ein Feld „admin“ gibt, worüber das Skript identifiziert, ob jemand Administrator-Rechte hat. Ein Möglicher GET-String könnte z.B. folgendermaßen aus sehen:
http://www.meinhost.com/kunde/?id=1;UPDATE+user+SET+admin+=+1+WHERE id+=+1;
Die resultieren SQL-Abfrage wäre dann:
SELECT * FROM user WHERE ID = 1;UPDATE user SET admin = 1 WHERE id = 1;
Das Semikolon wird als Trennzeichen zwischen zwei Abfragen aufgefasst. Somit werden bei der obenstehenden Abfrage eigentlich zwei Abfragen ausgeführt.
Wie man sieht, kann auf diese Weise jeder seinen eigenen Datensatz sehr schnell zu einem Administrator machen.
Häufige Fehler und Schutzmechanismen gegen SQL-Injektion
Einige Fehler beim Umgang mit Datenbanken im Zudammenhang mit Webapplikationen werden leider immer wieder gemacht. Dabei ist es eigentlich sehr einfach diese zu vermeiden:
Ein potenzieller Angreifer muss um Erfolgreich zu sein möglichst viel über die Datenbank-Struktur herausbekommen. Sehr häufig kann man in POST-Formularen folgenden Aufbau erkennen:
<form action="" method="post"> <input type="text" name="username" /> <input type="text" name="passwort" /> <input type="text" name="strasse" /> <input type="text" name="ort" /> usw. </form>
Die Datenbank hat dann meistens Felder, die genau so heißen wie die Input-Felder in der HTML-Datei.
Dementsprechend leiten sich meine ersten beiden Tipps zu Vermeidung von SQL-Injektion ab:
- Benutze niemals die gleichen Namen für Felder in einer Datenbank und in einem Formular!
- Verwende möglichst Feldnamen, die zwar logisch aber nicht einfach zu erraten sind!
Letzterer Tipp lässt sich zum Beispiel durch die Verwendung von Präfixen für die Spaltennamen realisieren.
Beispielsweise würde ich eine Beziehung des Präfixes zur Tabelle herstellen. Das Feld „username“ aus dem obigen Beispiel könnte dann user_username heißen. Bewährt haben sich auch verkürzte Präfixe, die mehrere willkürliche Buchstaben des Tabellennamen enthalten. So könnte aus dem Feld „id“ der Tabelle „herkunft“ „hrft_id“ werden. Diese Art der Feldnamen hat übrigens noch den weiteren Vorteil, dass wenn die Präfixe in einer Datenbank eindeutig gewählt werden als Fremdschlüssel auf einen Blick mit der verweisenden Tabelle in Verbindung gebracht werden können.
Darüber hinaus sollte man jegliche Daten, die vom User an den Server geschickt werden einer Filterung unterziehen. In den meisten Fällen sind von vorn herein nicht alle Zeichen für alle Datenfelder erlaubt. So könnte man Beispielsweise definieren, dass für den Benutzernamen nur Buchstaben und Ziffern akzeptiert werden. So könnte man für die meisten Datenfelder direkt einen Filter definieren. Dazu bietet es sich an, sofern man in einer objektorientieren Programmiersprache arbeitet für die Eingabe-Felder Klassen zu erzeugen, die dann wiederverwendet und bei Problemen entsprechend Zentral modifiziert werden können.
Viele Programmiersprachen bieten die Möglichkeit die Zeichenketten bevor sie in die Abfrage eingefügt werden auszumaskieren. So würde diese Technik die Injektion von oben in folgende Zeichenkette umwandeln:
SELECT * FROM user WHERE ID = 1\\;UPDATE\\ user\\ SET\\ admin\\ \\=\\ 1\\ WHERE\\ id\\ \\=\\ 1\\;
Damit würde zwar die Anweisung einen Fehler erzeugen weil das Feld ID (in der Regel) ein Integer sein sollte, aber das wäre immerhin schon einmal besser als den „Schadcode“ auszuführen.
Die beste und sicherste Methode SQL-Injektionen zu verhindern bzw. minimieren ist die Verwendung eines Datenbank-Framworks (wie z.B. Creole für PHP). Dabei werden in die Abfrage selbst nur Platzhalter für Dateneingaben eingefügt. Über eine Methode können diese Platzhalter dann durch die eigentlichen Daten ersetzt werden und entsprechend ihres Datentyps ausmaskiert werden. Sollte es dann doch einmal zu einem Problem kommen, kann dieser Fehler in dieser Software behoben und neu eingespielt werden ohne, dass seine eigenen Programme modifizieren muss.
Wenn man alle diese Tipps beachtet entwickelt man eine robuste Datenbank Anwendung, die wenigstens die Gefahr einer SQL-Injektion auf ein verträgliches mass minimieren kann.
Verwandte Artikel
Beitrag: 3. September 2007 (09:01 Uhr) von juniperus
Kategorien: Server, Linux, SQL, PHP, Programmierung
Tags: datenbanken, mysql, php, sicherheit, sql
Permanentlink: SQL-Injektion - Einblicke und Gegenmaßnahmen
Kommentarfeed abonnieren
Beitrag Kommentieren
TrackBack-URL







10 Kommentare zu “SQL-Injektion - Einblicke und Gegenmaßnahmen”
Sehr guter Artikel! Danke.
[…] hat einen - wie ich finde - ganz guten Artikel zum Thema SQL-Injection geschrieben. Sehr […]
Schöner Artikel. Zum Thema Filter bietet PHP5 seit der Version 5.2.0 mit den filter_*-Funktionen ( http://www.php.net/manual/de/ref.filter.php ) eine ziemlich mächtige Hilfestellung zum filtern von Daten verschiedenster Arten. Einen gutes Tutorial dazu gibt es hier: http://www.php.net/manual/de/ref.filter.php
mfg, mh166
Sorry, der zweite Link stimmt nich, das hier ist der korrekte Link zum Tutorial: http://phpro.org/tutorials/Filtering-Data-with-PHP.html
Irgendwas is hier schief gelaufen … Hier jetzt einfach noch mal den eigentlichen Post, diesmal gleich mit richtigem Link.
Schöner Artikel. Zum Thema Filter bietet PHP5 seit der Version 5.2.0 mit den filter_*-Funktionen ( http://www.php.net/manual/de/ref.filter.php ) eine ziemlich mächtige Hilfestellung zum filtern von Daten verschiedenster Arten. Einen gutes Tutorial dazu gibt es hier: http://phpro.org/tutorials/Filtering-Data-with-PHP.html
mfg, mh166
Hallo mh166,
Akismet hat irgendwie 2 Deiner Kommentare als Spam erkannt. Ich habs mal nachträglich freigeschaltet.
Vielen Dank für den Tipp - Das sieht wirklich sehr interessant aus. Damit werde ich mich mal eingehender beschäftigen.
[…] (more…) […]
SQL Injections…
Hallo,
ich habe heute nachdem ich über mehr Informationen zu dem Thema gesucht hab einen guten Beitrag über SQL Injections auf Guxx.de gefunden. Schaut ihn euch mal an, ist nicht sonderlich lang aber informativ.
Viel Spaß damit!…
Hi,
sehr gutes how-to!!! So macht die suche spaß im internet - wenn man gute artikel findet.
grüße
abend,
guter artikel - schließe mich obiger meinungen an.
dank an juniperus