PHP-Skripte absichern – Teil 1: (Remote) SQL-Injections
Hallo liebe Community,
in meinem ersten Tutorial möchte ich mich einem der größten Sicherheitsrisiken in PHP-Code widmen: den SQL-Injections. Darunter versteht man das Einschleusen von bösartigem Code in SQL-Abfragen des Scriptes.
Zum besseren Verständnis beginnen wir mit einem Beispiel:
Tatort: Benutzerdatenbank. Der Benutzer kann seinen Benutzernamen in einem Formular eingeben; der eingegebene Wert wird in der Variablen $name gespeichert. Dann kommt der Knackpunkt, nämlich die ungesicherte Datenbankabfrage:
php:
1:
mysql_query(“SELECT * FROM users WHERE username=’”.$name.”’”);
Der Angreifer gibt als Benutzernamen z.B. Folgendes an:
code:
1:
thaseek’; DELETE FROM users
Bei Datenbanksystemen, die solche „stacked queries“ unterstützen, ist die Benutzertabelle jetzt leer.
Das Problem ist, dass jeder Benutzer nach Belieben einzelne oder doppelte Anführungszeichen setzen (und damit die vorgesehene SQL-Abfrage erweitern) kann.
Um das zu vermeiden, müssen den Anführungszeichen Backslashes \ vorangestellt werden; man nennt das „escapen“. PHP bietet von Haus aus einen Mechanismus, der das bewerkstelligen kann, nämlich magic_quotes_gpc. Jedoch sollte immer der Escaping-Mechanismus der verwendeten Datenbank verwendet werden, da diese Option nur rudimentären (und verallgemeinerten) Schutz bietet.
Um also eine Ausgangsbasis für eine ordentliche Verarbeitung des Ganzen zu erreichen, müssen die Auswirkungen der Magic Quotes zuerst rückgängig gemacht werden, indem die eingefügten Slashes entfernt werden:
php:
1:
2:
3:
if(get_magic_quotes_gpc()) { //Magic Quotes sind aktiviert
$name = stripslashes($name);
}
Dann wenden wir die datenbankeigene Escape-Funktion an. Im Falle von MySQL ist das mysql_real_escape_string():
php:
1:
$name = mysql_real_escape_string($name);
Jetzt kann $name guten Gewissens eingesetzt werden.
Aber Vorsicht: Anders als gemeinhin angenommen, ist es mit mysql_real_escape_string() nicht immer getan, um SQL-Abfragen abzusichern. Zur Veranschaulichung wiederum ein Beispiel:
Angenommen, ihr habt ein Newsscript im Einsatz, das über folgende URL erreichbar ist: http://www.beispieldomain.de/news.php?id=XYZ , wobei XYZ natürlich durch einen ganzzahligen Wert zu ersetzen ist, anhand dessen der Newseintrag in der Datenbank gesucht wird:
php:
1:
2:
3:
4:
5:
6:
7:
$id = $_GET[‘id’];
if(get_magic_quotes_gpc()) { //Magic Quotes sind aktiviert
$id = stripslashes($id);
}
$id = mysql_real_escape_string($id);
$query = "SELECT * FROM news WHERE id=".$id;
$result = mysql_query($query);
Ein Angreifer vermutet eine solche Sicherheitslücke und ruft die Seite mit einem modifizierten Parameter auf: http://www.beispieldomain.de/news.php?id=1;DELETE%20FROM%20news
Damit ließe sich der Inhalt der gesamten Newsdatenbank löschen, ohne die Zugangsdaten zur Datenbank zu kennen.
Moment mal, werden jetzt einige sagen, wo ist hier eigentlich eine Sicherheitslücke?
Die Crux liegt im verwendeten Datentyp, denn der erwartete Integerwert wird ohne rahmende Anführungszeichen verarbeitet; der schöne Escaping-Mechanismus läuft also ins Leere.
Um dem abzuhelfen, muss der Wert der Variablen vor der Verwendung unbedingt auf den gewünschten Datentyp gebracht werden.
Erste Möglichkeit: umwandeln mittels der Funktion intval():
php:
1:
$id = intval($id);
Zweite Möglichkeit: Klassisches Typecasting:
php:
1:
$id = (int) $id;
Anschließend kann $id in der Datenbankquery eingesetzt werden.
So, fürs erste wären wir soweit – ich hoffe, dass ich euch mit diesem Tutorial weiterhelfen konnte. Trotzdem ist das noch nicht alles, was man bei SQL-Abfragen beachten sollte. Auf Wunsch gibt es dazu demnächst mehr
Danke fürs Lesen & stay tuned for my next contribution
Hey, hast ja doch noch an uns gedacht
Habe dir ja vor einiger Zeit in ICQ schon gesagt, dass ich das Tutorial sehr gut finde!
Daher nochmals vielen Dank
also dadurch das ich mich mit den injections ned so auskenn und glaub da braucht man ja perl kenntnisse dazu hab ich einfach mal die version mit der url probiert.
hat aber nix gemacht hat einfach meine error seite angezeigt..
abgesehen davon: ich weiß nicht genau, was du ausprobiert hast; der code da oben ist nur zur grundsätzlichen verdeutlichung der problematik da. (die einschränkung steht indirekt im text, mysql_query unterstützt nämlich kein stacking, steht damit aber allein auf weiter flur...)
Original von Babbsdrebbler
Oder bei id auch is_numeric() wenn man die Sachen vorher schon überprüft hat man nachher weniger Arbeit.
Und bei Passwörtern würde ich mir per SQL erst die userdaten ziehen (abfrage per name) und dann die Passwörter in PHP vergleichen.
ich würde - wenn überhaupt - für is_int() plädieren; is_numeric() lässt so einige werte durch, die man im falle des obigen beispiels nicht haben will
ich wollte hier übrigens den schnellsten weg zeigen, und das sind nunmal die beiden einzeiler.
bzgl. den passwörtern widerspreche ich nebenbei bemerkt nicht - ich habe aber auch nichts anderes behauptet.
This post has been edited 1 time(s), it was last edited by thaseek: 22.12.2007 11:54.
PHP-Skripte absichern - Teil 1: (Remote) SQL-Injections
EIn Auszug aus includes/funcions_main.php meiner eigenen Forensoftware
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
// Eigene addslashes-Funktion deklarieren.
// Der Optionswert für magic_quotes_gpc spielen damit praktisch keine Rolle.
if (get_magic_quotes_gpc() == 0)
{
function em_addslashes($string) {return addslashes($string);}
function em_unaddslashed($string) {return strtr($string, array('\\\\' => '\\', '\\' => ''));}
}
else
{
function em_addslashes($string) {return $string;}
function em_unaddslashed($string) {return $string;}
}
schönes tutorial, mache es auch so ähnlich. habe alle sonderzeichen in einem array getan und fals da einer drinn vorkommt -> error <- fragt er nix in der mysql ab.
If you were enjoying this post and if you keen on reading more interesting stuff then do not hesitate to complete the free sign up.
After the free registration you will gain access to all areas and you will be able to communicate with other artists from all over the world.
In addition you will benefit from our Photoshop and coding section as well as from our huge (hundreds of gigabytes) free resource section where you can find everything you will need to be a successful (web) designer/artist.
Sign up now and enjoy the advantages as a registered member.
(This website will be ad-free after a complete free sign up.)