Frage von RaceShafter, 67

Ist dieser PHP MySQLi Befehl richtig?

Ich möchte SQL-Injektion verhindern.

Meine Verbindung mit der Datenbank:

$dbconnect = mysqli_connect(######);

Das Testen auf Sonderzeichen:

$string = mysqli_real_escape_string($dbconnect, $string);

Sind die jeweiligen Code-Abschnitte richtig? Wird nun der $string gesichert übertragen und Injektionen nun verhindert?

Gruß

Antwort
von RakonDark, 40

Ich glaub Du hast injections und die protection via mysqli noch nicht im überblick .

generell kann immer ein angriff erfolgen ob nun mysql oder mysqli solange der query einfach so abgesetzt wird .

deswegen erfand man den prepared statement , dieser wird dann unabhängig mit variablen gefüllt , erst das macht es sicherer , da dabei kein zusätzlicher query entsteht .

$stmt = mysqli->prepare("SELECT col1 FROM t1 WHERE col2 = ?");
$stmt->bind_param("s", $col2_arg);
$stmt->execute();

das $stmt->bind_param("s",$cols2_arg); bindet den wert so ein das eben kein zusätzlicher query entstehen kann ,

dein mysqli_real_... ist wie auch schon bei mysql_real_.... keine sichere Lösung .

Kommentar von RaceShafter ,

Also Verbindung:

$dbconnect = mysqli_connect(######);

Und Sicherung (Das $dbconnect muss da doch auch hin oder? Und wofür steht das "s"? Und $stmt->execute heißt, dass der SQL Befehl dann ausgeführt wird oder?):

$stmt = mysqli->prepare($dbconnect, "SELECT `string` FROM `example` WHERE `string` = '$string'");
$stmt->bind_param("s", $string_arg);
$stmt->execute();
Kommentar von Malemeister ,
Kommentar von RaceShafter ,

Habe es nun durchgelesen und mich selbst dranprobiert. http://pastebin.com/GhFpBYGW

Ist das so richtig?

Kommentar von RaceShafter ,

EDIT: Nun bekomme ich folgenden Fehler, während es aber funktioniert. Also es wird eingetragen, doch ich mag keine Fehler..:

Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in C:\Users\Tom\Documents\XAMPI\htdocs\test.php on line 6

Kommentar von Malemeister ,

Nein, das ist so nicht richtig. Du hast dir das auch nicht richtig durchgelesen und auch nicht verstanden.

Du solltest dir mal genauer anschauen warum du überhaupt bind_param benutzen sollst bzw. wofür du dies brauchst.

Das ist dort aber auch super erklärt.

Kommentar von RaceShafter ,

Ok. Habe es mir ja schon durchgelesen. Ich lese es mir nochmal durch. Moment.

Kommentar von RaceShafter ,

Alles klar. Mein Fehler war das Fragezeichen. Ich habe das so verstanden, dass bei $stmt auch schon die Strings angegeben werden müssen. Ist nicht der Fall, sondern da sollten die Fragezeichen hin, der String wird erst beim Binden angegeben. BZW. wenn es mehrere sind, die Strings. Jetzt habe ich es schon mehr verstanden. Der Code gibt keinen Fehler aus. Ich werde das Ganze Geschehen sowieso noch mehrere Male mit verschiedenen  SQL-Befehlen schreiben müssen, dann präge ich es mir immer mehr ein. Aber schon mal ein großer Schritt mehr, zu wissen, wie sich SQL-Injektion verhindern lässt. Mein Projekt soll später für alle Leute veröffentlicht werden, die sich nicht viel mit PHP auskennen und eine Login und Registrierungsfunktion haben wollen. Die erste Version ist jetzt schon zu finden. Was das "s" angeht habe ich auch schon verstanden. Es steht für String und bedeutet, dass es sich im SQL-Befehl um eine Stringauslesung oder um ein Stringupdate oder um ein Stringinsert handelt. Danke für deine Hilfe.

Kommentar von RakonDark ,

ich finde PDO schöner, da kann man seinen parametern einen schicken namen verpassen :)  Macht die sache durchaus Fehlerfreier und lesbarer  :)

Kommentar von Malemeister ,

http://php.net/manual/de/mysqli.real-escape-string.php

Warum ist real_escape nun keine sichere Lösung? Bin auf die Antwort gespannt...

Kommentar von RaceShafter ,

Keine Ahnung.

"generell kann immer ein angriff erfolgen ob nun mysql oder mysqli solange der query einfach so abgesetzt wird ."

Verstehe ich nicht. Du Real_Escape_String wird der doch auch geprüft und nicht einfach so abgesetzt?

"deswegen erfand man den prepared statement , dieser wird dann unabhängig
mit variablen gefüllt , erst das macht es sicherer , da dabei kein
zusätzlicher query entsteht ."

Was fürn zusätzlicher Query? Ich verstehe es nicht, genau so wenig wie der Code davor, mit "s" und ob dort $dbconnect rein soll.


EDIT: Habe jetzt den Link lesen und verstehen gesehen. Lese mir das eben durch.

Kommentar von Malemeister ,

Die Frage war auch nicht an dich sondern an den Antworgeber gerichtet. real_escape String ist, wie du auch schon richt erkannt hast, sicher wenn du es richtig benutzt.

Kommentar von RaceShafter ,

Ok, dann lag ich in dem Punkt ja schon mal richtig :D

Kommentar von maximilianus7 ,

real_escape_string macht es genau so sicher. der vorteil des prepare mit ersatzvariablen (? und :xy) ist, dass die sicherheit an einer stelle konzentriert ist.

Kommentar von RaceShafter ,

An einer Stelle konzentriert? Wie meinst du das? Und nach all den Nachrichten mal Danke für die Hilfe und Sry für meine Ungeduld.

Kommentar von RakonDark ,

zu deiner frage ,
Was fürn zusätzlicher Query?

wenn man verkettungen aufbaut , siehe meine Antwort unten , dann ergibt sich nicht nur ein Select sondern eine verlängerung deines Querys , der durchaus dann geparst wird und so ausgeführt wird .

wenn das ganz aber mit prepare erfolgt, wird zuerst der sql befehl geparst und die variablen danach eingesetzt damit wird der sql befehl nicht mehr verändert . somit kann der sql befehl nicht anders sein als im prepare angegeben .

Kommentar von RakonDark ,

wenn nicht richtig angewendet ergeben sich folgende angriffsmöglichkeiten

http://www.webappsec.org/projects/articles/091007.txt

daraus folgt, das du bei jedem query selber überlegen musst ob das real_escape richtig angewendet wurde .

ergo ist bind_param immer sicher und real_escape nur sicher wenn es richtig benutzt wird .

Keine passende Antwort gefunden?

Fragen Sie die Community

Weitere Fragen mit Antworten