Heute geht es wiedermal um die Sicherheit in PHP.
Diesmal fahr ich fort mit dem Teil 2 dieses Themas.
Nun geht es nicht mehr um Local File Includes(LFI), sondern
um Error-Based SQL-Injections.
Zum Anfang, was sind überhaupt SQL-Injections?
SQL-Injections sind Sicherheitslücken innerhalb von Scripten/Software, über
die es möglich ist unauthorisiert Datenbanken beliebig auszulesen.
Diese Lücken sind besonders kritisch, da gerade sowas ein guter Einstieg ist um
beispielsweise Administrator-Daten auszulesen um sich dann darüber als Administrator in dem
jeweiligen CMS anzumelden, um darüber dann weitere Rechte im System zu gewinnen oder um
Kunden bzw. Useraten auszulesen.
Zum Anfang erkläre ich wie man am besten nicht programmieren sollte.
Nehmen wir an wir setzen unsere GET-Paremeter oder POST-Parameter direkt in das SQL-Statement ein,
wenn wir aus einer Tabelle Beispielsweise einen News-Eintrag lesen möchten.
Titel: | |
Artikel: |
Dies ist unser kleines Script, zum einblenden einer News wo die ID angegeben ist.
Hier wäre eine klassische Error-Based SQL-Injection möglich, sowas ist im großen und ganzen „tödlich“.
Nehmen wir an wir haben neben unserer Tabelle „article“ eine Tabelle „users“ mit den Attributen „id“, „username“ und
„password“ wo das Passwort im schlimmsten Falle in plaintext vorliegt.
Nun wäre es einem Angreifer leicht möglich darüber die Daten aus der Tabelle „users“ auszulesen.
Der Angreifer würde an dieser Stelle erstmal testen ob überhaupt ein Fehler auftritt wenn der GET-Parameter verändert werden würde:
Erst einmal zum Beweis das unser Script ohne Eingriffe von anderen „exzellent“ läuft hier ein Screenshot:
Nun als Beweis das ein Fehler auftreten würde, wenn der Parameter verändert werden würde bzw. das gar kein Content wiedergegeben werden würde:
Nun würde ein Angreifer versuchen aus der Datenbank die Spalten zu ermitteln wo eine Ausgabe von Daten möglich wäre,
dies erläutere ich hierbei nicht wie das ganze exakt funktioniert.
Hier wird dem Angreifer ausgegeben welche Spalten sich zum Ausgeben vom Content eignen. Er sieht zwei verschiedene Zahlen die ausgegeben werden.
Die Zahl 2 und 3.
Darüber würde er versuchen sich Inhalt ausgeben zu lassen z.B. die Tabellennamen bzw. zum Anfang überhaupt die MySQL Version um darüber zu entscheiden wie er weiter
fort fährt.
hier sieht der Angreifer die Tabelle users und die erste Spalte dieser Tabelle „id“.
Nun könnte er durch das verändern des Limits die weiteren Spaltennamen auslesen um durch die gewonnen Informationen die Tabelle auszulesen.
hier hat der Angreifer die erste Spalte der Tabelle users ausgelesen.
Damit hat der jenige nun die Administrator-Logindaten.
Um dies zu vermeiden gibt es nun 2 Optionen.
Entweder man nutzt die Funktion „mysql_real_escape_string“ um die Parameter zu filtern, dabei müssen allerdings innerhalb des SQL-Statements
einfache Anführungszeichen um die Variable die gefiltert wurde gesetzt werden
$sql = "SELECT * FROM article WHERE id='".mysql_real_escape_string($_GET["id"])."';";
oder man setzt gleich vom beginn an Prepared Statements ein.
Die zweite Variante ist hierbei die klügere und vor allem saubere.
Dazu gibt es in diesem Artikel mehr:
http://blog.php-developement.info/?p=18