phpbar.de logo

Mailinglisten-Archive

[php] sichere MySQL Queries

[php] sichere MySQL Queries

AA aa at geb-team.de
Don Nov 9 14:30:29 CET 2006


hallo,

zum semikolon-märchen:
----------------------
das mit dem semikolon im query ist eine legende. mysql und mysqli 
filtern dies heraus. das steht auch im handbuch:

"The query string should not end with a semicolon."

aus bestimmten gründen, kann dies aber gewollt sein (mehrere queries in 
einem befehl). dafür liefert mysqli die funktion/methode 
mysqli_multi_query() / multi_query():

"executes one or multiple queries which are concatenated by a semicolon."

zum einsatz von prepared statements als heilmittel:
---------------------------------------------------
schickes feature :)
was dagegen spricht: will man eine portable anwendung schreiben (zb. mit 
der PDO-erweiterung), sollte man dies tunlichst unterlassen. leider 
findet sich dieser entscheidende hinweis nicht überall da, wo er 
hingehört. aber zumindest wird es bei PDO-mysql in einem nebensatz erwähnt:

"If you're writing portable code, you should use 
PDOStatement::fetchAll() instead."

zur eigentlichen frage: "sichere mysql-queries?"
------------------------------------------------
das ist ein komplexes thema und lässt sich nicht mit einer formel 
beantworten. es gibt allerdings eine grundregel: text, der in ene db 
gespeichert wird, muss escaped werden.

da allerdings gibt es ein paar hürden. eine davon ist, dass man meistens 
  zu lesen bekommt, "musst du mit addslashes() oder der entsprechenden 
funktion für mysql oder mysqli machen". einfach, nicht wahr?

das stimmt aber nur bedingt: in abhängigkeit von servereinstellungen 
steht der input aus formularen oder get-parametern (achtung, auch 
cookie-werte!!) bereits escaped vor der tür. führt man hier einfach 
dumpf (siehe oben) das addslash() oder sonstige funktionen aus, legt man 
sich ein grosses ei ins nest: aus "aa's" wird zunächst "aa\'s" und dann 
durch add_slashes() ein "aa\\\'s"

auf einigen websites sieht man das sehr hübsch, wenn dann doubel quotes 
so dargestellt werden: \"foobar\"

wenn man das einmal so in der db hat, kann man sich auf en verlängertes 
wochenende einstellen, das wieder zu filtern. denn ein strip_slashes() 
entfernt zwar alle slashes, aber auch gewollte slashes... :)

schuld an diesem mist ist die einstellung für "magic_quotes", die leider 
so voreingestellt ist, dass anfänger nicht gleich beim ersten projekt in 
die scheisse greifen. es werden per default bereits die GPC-daten 
escaped auf den meisten servern! das ist gut für queries, nicht aber 
beim versenden des textes per email (da muss das unescaped rein).

das heisst, man muss nicht nur darauf achten, strings escaped in die db 
zu speichern, sondern auch, ob diese eventl. schon escaped sind. daten 
aus einem db-query, welche weiterverabeitet wieder zurückgespeichert 
werden, sind nicht escaped. man muss also zusätzlich auf die herkunft 
der variablen achten.

daher meine ausdrückliche empfehlung:

anstatt wie bekloppt auf tot und teufel zu prüfen, sollte man 
sicherstellen, dass zunächst *keine* automatische umwandlung erfolgt. 
dann hat man die daten immer in der gleichen form (unescaped) - und zwar 
unabhängig von der herkunft (session, get, post, get, request, server, 
env, interne variablen...). umsetzung: mit get_magic_quotes_gpc() 
prüfen, ob automatisches escapen erfolgt. wenn ja, dann stripslash() auf 
  alle GPC-daten. da gibt es im netz hübsche funktionen mit array_map, 
etc., wo sich das mit einem 3 zeiler erledigen lässt.

dann achtet man bei queries einfach darauf, dass strings mit der 
entsprechenden funktion escaped werden. wobei addslashes() die 
schlechteste wahl ist, aber für gängige angriffe ausreichend ist.
besser ist, die jeweilige funktion der db-schnittstelle zu nutzen, weil 
die nämlich den jeweils benutzten charset berücksichtgen! gerade bei 
utf-8 ist das kein kinderspass mehr, den man mit addslashes abbügeln kann.

also:

addslashes(): in grenzen ausreichend
besser: mysql_escape_string(), mysqli_escape_string(), 
mysqli_real_escape_string() und konsorten verwenden.

wer mehr zu diesem leidigen thema nachlesen will:
http://de3.php.net/manual/en/security.magicquotes.php

dort wird das alles nochmal etwas ausführlicher dargestellt.

Lutz Zetzsche wrote:
> Hallo Peter,
> 
> Am Donnerstag, 9. November 2006 13:17 schrieb Peter Prochaska:
>> Lutz Zetzsche schrieb:
>>> jetzt hast Du mich abgehängt. Also noch mal langsam für Dumme...
>>> Was verwendet er und welches Problem hätte er nicht? :-)
>> Bei MySQL kann man bei mysql_query kein ; in einem Query angeben. Da
>> wird ein Fehler geworfen.
>> Da hat man das Problem mit ;DROP table 'x' nicht :-)
>>
>> Bei Oracle usw. aber schon...
> 
> ah, verstehe. Das war mir gar nicht bewußt, daß das so mit dem Semikolon 
> bei MySQL nicht funktioniert. Wieder was gelernt. Danke! :-)
> 
> Viele Grüße
> Lutz

php::bar PHP Wiki   -   Listenarchive