Was ist ein \"Prepared Statement\"? Vor was schützt es und wie tut es das?

Begonnen von k00ni, 24. April 2007, 15:37:56

Vorheriges Thema - Nächstes Thema

k00ni

Hallo,
auf der Seite www.strassenprogrammierer.de habe ich einen Artikel über Prepared Statements gelesen. Viele wissen garnicht, dass dies eine sehr effektive Möglichkeit ist, seine SQL-Statements zu schützen. Zwar ist, wie überall auch, kein 10.000 prozentiger Schutz garantiert, aber es dürfte Angreifern (sind nicht immer Hacker /uploads/emoticons/icon_e_wink.gif.3167d127940f44558fbf1ccd9b6d60a9.gif\" alt=\";-)\" /> ) sehr schwer fallen, dies zu kompromittieren, also zu täuschen.
 
Um was geht es eigentlich?
Viele PHP-Entwickler schreiben direkt in ihren Quellcode die SQL-Statements. Dies hat den Vorteil, dass bei der Verwendung von internen Variablen, wo von Außen keinerlei Zugriff besteht, auch (fast) keine Probleme im Bezug auf Sicherheit auftreten können. Denn wie will man die ändern?
Da aber sehr viele Skripte die Eingabe von Seiten der User verarbeiten, besteht hier ein sehr großes Potenzial an Angriffsmöglichkeiten, bspw. SQL-Injections (Einschleusen von eigenem SQL-Code in bestehende Variablen).
 
Der Ansatz
Der Ansatz ist, dass man die Variablen, die von Außen kommen, nicht extra immer und immer wieder prüft, sondern dass man das eigentliche SQL-Statement inklusive der einzusetzenden Variablen an eine Funktion übergibt. Das SQL-Statement enthält sogenannte Platzhalter für etwa nummerische Werte oder Zeichenketten, welche dann von den übergebenen Variablen eingenommen werden. Der Query wird ohne die Platzhalter vom Server direkt abgearbeitet (kompiliert) und es wird von ihm eine grobe Struktur erstellt. Danach werden in die Platzhalter die Variablen eingesetzt, je nach Typ und Anordnung.
Es soll nun sehr schwierig sein, kompromittierten Code einzuschleusen, da er ja die Grundstruktur verändern würde, was zu einem SQL-Fehler führt.
 
Beispiel:
Übergibt man also mit einer kompromittierten Variable ($name) folgenden SQL-Befehl
 

 xy\';drop database();# 

 
 
in das Statement
 

$sql = \"SELECT * FROM user WHERE name=\'$name\' \" 

 
 
So würde dass am Ende folgendermaßen aussehen:
 

SELECT * FROM user WHERE name=\'xy\'; 
drop database();
#

 
 
Folgendes könnte nun passieren: Der erste Teil des SQL-Statement würde abbrechen, da es bestimmt keinen Namen \"xy\" geben würde. Im zweiten Teil würde das drop database (); ausgeführt werden, wenn der ausführende User die Rechte dafür besitzt. Etwas blöd, wenn einem das passiert /uploads/emoticons/icon_e_wink.gif.3167d127940f44558fbf1ccd9b6d60a9.gif\" alt=\";-)\" />
(Dieses Beispiel ist von www.strassenprogrammierer.de)
 
Erweiterungen
Ich hoffe, ich habe hier etwas die Problematik erläutert, die bei der unbedachten Nutzung von (aus bspw. Formularen) übergebenen Variablen entstehen kann. Ich selbst nutze eine zentrale Funktion, die mir alle Statements zusammenbaut. In diesem Zusammenhang habe ich noch die Funktion mysql_real_escape_string eingebaut, die spezielle Zeichen maskiert. Man könnte hier noch weitere Abfragen oder Prüffunktionen einbauen bzw. implementieren. Denkbar wäre die Prüfung der Datentypen der übergebenen Variablen.
 
Grüße

mahe

du solltest ev. erwähnen dass das mit mysql nicht möglich ist, sondern mit mysqli

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


k00ni

Hallo,
wo besteht da der Unterschied? Hättest du nen Link? Anbei, ich kann den Post nicht ändern -.- Keine Ahnung, aber das scheint hier in einigen Boards nicht zu gehen.
 
k00ni

mahe

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


dec

ich baue bei mir diese funktion ein, um die einfachsten \\\"bad requests\\\" abzufangen:

 $value) $_REQUEST[$key] = addslashes(strip_tags($value));
foreach ($_GET as $key => $value) $_GET[$key] = addslashes(strip_tags($value));
foreach ($_POST as $key => $value) $_POST[$key] = addslashes(strip_tags($value));
}
?>

spass ist, was ihr draus macht


k00ni

Kleine Frage: Mit dem reinigen von $_REQUEST dürftest du doch auch $_GET und $_POST gecleant haben oder?
Mahe schrieb, dass mysql_real_string_escape nur bei mysqli funktioniert. Was gibts da für Alternativen, wenn dies nicht installiert ist?
 
Grüße

mahe

Das hab ich nicht geschrieben ...
DEC:
Was machst du wenn zB $_REQUEST[\'foobar\'] ein Array ist?
Wenn magic_quotes_gpc auf On steht dann hast du doppelte Backslashes ...

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


k00ni

du solltest ev. erwähnen dass das mit mysql nicht möglich ist, sondern mit mysqli[/quote]
 /uploads/emoticons/icon_e_sad.gif.cc8ba2b6b966c5e020020efa47702aab.gif\" alt=\":(\" />  Dann bitte ich um Erklärung.

mahe

in dem Artikel gehts ja um was ganz anderes den du erwähnt hast und da wird dies auch mit mysqli erklärt.
Worauf ich dann nachgesehn hab und feststellte dass es das nur bei mysqli gibt.

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


Powie

... und damit für die breite Masse an Usern nicht benutzbar ist  [/uploads/emoticons/icon_e_surprised.gif.a005678239f11b45b64b526b2c82e9a1.gif\" alt=\":o\" />]

dec


Original von mahe ...
DEC:
Was machst du wenn zB $_REQUEST[\'foobar\'] ein Array ist?
Wenn magic_quotes_gpc auf On steht dann hast du doppelte Backslashes ...
[/quote]
array: dann müsste man die funktion weiterentwickeln /uploads/emoticons/icon_e_wink.gif.3167d127940f44558fbf1ccd9b6d60a9.gif\" alt=\";-)\" /> (rekursives runderbeten)
doppelte backslashes: ist mir bis jetzt noch nicht passiert. und wenn, dann kann man simple mit str_replace das ganze doppeltgemoppelte wieder rausnehmen, falls es wirklich passieren sollte.

spass ist, was ihr draus macht


mahe

Dann hast du aber wieder ein Problem wenn da wirklich 2 sein sollten /uploads/emoticons/icon_e_biggrin.gif.1a84f5257b36e14b36d04985314f877f.gif\" alt=\":-D\" />

http://blog.mahe.at\" rel=\"external nofollow\">http://blog.mahe.at/wp-content/uploads/2007/06/88x31_1.jpg\" alt=\"88x31_1.jpg\">


Ja, diese Signatur dient zur Werbung!


Und dass ich meine Posts wiederfinde ...


dec

/uploads/emoticons/icon_e_biggrin.gif.1a84f5257b36e14b36d04985314f877f.gif\" alt=\":-D\" /> hehe unwahrscheinlich /uploads/emoticons/icon_e_smile.gif.f7ec63a2b1c3d90a9415e40455642502.gif\" alt=\":-)\" /> ^^

spass ist, was ihr draus macht


all your base are belong to us