16.18. Wie kann ich bösartigen Code in SQL-Abfragen unterbinden?Antwort von Alex KieselIn nahezu allen Einsatzgebieten einer Datenbank wird die Datenbank durch ein bestimmtes Benutzerinterface (z.B. über das Web) abgefragt und auch gefüllt. Oft darf ein bestimmter Benutzer nicht alles sehen, was sich in der Datenbank befindet - und schon gar nicht ändern oder löschen. Falsch programmierte Scripte ermöglichen jedoch genau dies - dabei ist ein Schutz gegen die als SQL-Injection bekannte Technik gar nicht so schwer. Auf die Prüfung der übergebenen Parameter kommt es an. (Siehe dazu auch Prüfe importierte Parameter. Traue niemandem). Zunächst mal ein Beispiel, wie eine solche SQL-Injektion aussehen könnte: in einer Benutzerverwaltung darf ein User genau sein eigenes Passwort ändern. Wir haben also die Tabelle "account", die insbesondere die Logindaten des Users und des Admins enthält. Der Benutzer sendet das Passwort-Ändern-Formular in seinem Browser ab und serverseitig wird das neue Passwort in die Datenbank geschrieben: $result= $db->update (' update account set password= "'.$_REQUEST['newpassword'].'" where username= "'.$_REQUEST['username'].'"' ); Hier wird die Variable $_REQUEST['newpassword'] nicht geprüft - der Benutzer kann eintragen, was er möchte. Mit etwas Trial-and-Error findet der Benutzer heraus, dass er die doppelten Anführungszeichen (") als String-Delimiter benutzen muss; er gibt nun ein Passwort seiner Wahl und als Username userxy" or username="admin. Somit ergibt sich nach der Textersetzung folgendes SQL: update account set password= "adminsuxx" where username="userxy" or username="admin" Es kommt hier also hochgradig darauf an, niemals fremden Parametern zu trauen. Auf was muss also getestet werden? Parameter, die innerhalb von Quotes als String an die Datenbank übergeben werden sollen, dürfen selbst keine ungeschützten Quotes enthalten. Parameter, die IDs oder Zahlen repräsentieren, dürfen nur Ziffern enthalten. Die beiden Funktionen sichern genau dies, und sorgen zudem dafür, dass NULL-Values korrekt wiedergegeben werden: function sqlSafeString($param) { // Hier wird wg. der grossen Verbreitung auf MySQL eingegangen return (NULL === $param ? "NULL" : '"'.mysql_escape_string ($param).'"'); } function sqlSafeInt($param) { return (NULL === $param ? "NULL" : intVal ($param)); } (Die genauen Vorgaben zum Schützen von Sonderzeichen hängen vom SQL-Dialekt des RDBMS ab und müssen gegebenenfalls angepasst werden.) Man hätte so oben beschriebenes SQL so umschreiben können: $result= $db->update (' update account set password= '.sqlSafeString ($_REQUEST['newpassword']).' where username= '.sqlSafeString ($_REQUEST['username']) ); Obiger SQL-Injection-Versuch wäre dann gescheitert (weil keine Zeile auf diesen Usernamen matcht): update account set password= "adminsuxx" where username="userxy\" or username=\"admin\"" Eine Funktion, die komfortable SQL-Manipulation mit automatischem Escaping bietet, wird in String-Quoting bei Sybase vorgestellt; sie ist zwar für Sybase geschrieben worden, lässt sich aber leicht für andere Datenbanksysteme adaptieren. |
||
16.18. Wie kann ich bösartigen Code in SQL-Abfragen unterbinden? http://www.php-faq.de/q/q-sql-injection.html |
||
Archiv der de.comp.lang.php-FAQ Dies ist eine Archivseite von 2008 und wurde seitdem nicht geändert. Das dclp-FAQ-Team |