[Mysql-PHP] mysql_fetch_??

  • bez. htaccess :
    Wie stelle ich es richtig ein, damit nur Personen mit einem user_lvl, der höher als 1 ist zugriff auf das acp-login haben ?

    Durch die htaccess kann man das Verhalten des Webservers auf einem etwas niederen Level steuern, als es in PHP moeglich ist. Das bedeutet, aber auch, dass man nicht die gleichen Moeglichkeiten, wie in PHP (Zugriff auf SQL-Server) hat.
    Was man aber mit einer htaccess Datei machen koennte, ist den gesamten Admin-Bereich mit einem Passwort schuetzen, oder den Bereich nur fuer bestimmte IP-Adressen sichtbar/nutzbar machen: http://de.selfhtml.org/serverc…ess.htm#verzeichnisschutz


    Ist dieser Query "sicher und richtig" ausgeführt, egal was in meinem string steht ?

    PHP
    $nummer = "1";
    $query = sprintf("SELECT name FROM tabelle1 WHERE nummer='$nummer'",
                mysql_real_escape_string($nummer));
    $abfrage = mysql_query($query);

    Nein so wie es hier ist, ist es nicht sicher. Wenn man die "-Anfuehrungszeichen verwendet, dann ersetzt PHP, die $variablen mit deren Inhalt. (Setze $Test = 'Hallo Welt' und vergleiche: echo "$Test" mit echo '$Test'. Das erste gibt "Hallo Welt" und das zweite "$Test" aus.)
    Man hat in diesem Beispiel also schon, bevor sprintf ausgefuehrt wird "SELECT name FROM tabelle1 WHERE nummer='1'".
    Zudem ist der format-Text fuer sprintf nicht korrekt. sprintf ist vergleichbar mit 'format' in Pawn und braucht ein %d, %s, oder aehnliches um zu wissen, wo etwas eingefuegt werden soll. (Siehe: http://www.php.net/manual/de/function.sprintf.php)
    Das real_escape_string ist hier also Wirkungslos, da $nummer durch die "-Anfuehrungszeichen direkt gesetzt wurde und sprintf nicht weiss, wo es den String einsetzen soll.


    Folgende zwei Versionen sind sicherer:
    1. $query = sprintf("SELECT name FROM tabelle1 WHERE nummer='%s'", mysql_real_escape_string($nummer));
    2. $query = sprintf("SELECT name FROM tabelle1 WHERE nummer='%u'", $nummer);


    Version 1 ist das, was Du in Deinem Codebeispiel vorhattest. Es fuegt den mit mysql_real_escape_string gesicherten String ein.
    Version 2 ist moeglich, da nach einer Nummer gesucht wird. Mit %u wird $nummer zu einer positiven Nummer konvertiert. (Soll die Nummer negativ sein koennen, so verwendet man %d.) Wenn man also als Nummer "abc" eingibt ist spaeter im Query trotzdem eine Zahl (die 0) eingefuegt. Deswegen kommen wir hier Sicherheitstechnisch auch ohne real_escape aus. In der ersten Version haetten wir bei Eingabe von 'abc' keine Zahl, sondern die Zeichenkette 'abc' stehen, da wir es als String eingefuegt haben.


    Man kann aber auch ganz auf den Aufruf zu sprintf verzichten:
    1. $nummer = mysql_real_escape_string($nummer); $query = "SELECT ... nummer='$nummer'";
    2. $nummer = intval($nummer); $query = "SELECT ... nummer='$nummer' "


    Version 1 nutzt mysql_real_escape_string. Da wir doppelte Anfuehrungszeichen verwenden wird an der Stelle, wo $nummer steht die Variable eingefuegt. Wir sparen uns dadurch sprintf, oder das zusammen fuegen von einzel Strings ("SELECT ... nummer='" .$nummer ."'").
    Version 2 sieht ein wenig unsicher aus, da keine SQL-Spezifischen escape_* funktionen verwendet wurden, aber, da wir die Zeichenkette (aehnlich wie in dem zweiten sprintf Beispiel) mit intval() (http://www.php.net/manual/de/function.intval.php) in eine Zahl umgewandelt haben kann hier so leicht nichts mehr passieren.
    Hier gilt das gleiche, wie bei den sprintf Versionen. Die erste Version kann Zeichenketten beinhalten, die zweite Version nur Zahlen, auch, wenn jemand 'abc' eingibt.



    PHP
    $abfrage = mysql_query($query);

    Gerade waehrend der Entwicklungsphase, wenn man den Query oefters mal aendert, wuerde ich hier etwas in folgender Art hinzufuegen (die = exit = Programm abbruch, man sollte vorher aber die Datenbankverbindung beenden) : if(!$abfrage) exit('Der Query ist fehlgeschlagen. MySQL meldet: '. mysql_error());
    So kann man waehrend der Entwicklung sehen, wodran es liegt, wenn der Query fehl schlaegt. (Zum Beispiel bei einem Syntax error in dem Query String.)


    PHP
    $array = mysql_fetch_array($abfrage);
    echo $array["name"];

    Es wird zwar funktionieren, sofern eine Zeile mit nummer = 1 existiert, aber wenn eine Zahl angegeben wird, die nicht existiert, dann wird eine von PHP generierte Fehlermeldung sichtbar sein. Um dies zu verhindern, sollte man das vorher abfangen und dem Nutzer eine Fehlermeldung zeigen (es sieht einfach professioneller aus, wenn man die Fehlermeldungen selbst darstellt) :

    PHP
    $array = mysql_fetch_array($abfrage);
    if(!$array) exit("Die von Ihnen angegebene Nummer ist uns leider unbekannt.");
    echo $array["name"];

    Es geht darum, dass, wenn mysql_fetch_array FALSE wiedergibt, dass dann nicht "echo $array["name"]" ausgefuehrt wird, sonst gibt es eine (je nach Server/PHP Einstellung) Fehlermeldung von PHP.



    Hier das ganze nochmal zusammengefasst. (Ohne mysql_close(), was eigentlich bei einem guten Programmierstil, nach mysql_error(), wenn vorhanden, und vor exit() aufgerufen werden sollte.)

    Der Grund, weswegen ich hier mysql_error() nicht direkt eingefuegt habe ist, dass diese Nachricht dem Besucher sichtbar sein wird. Wenn die PHP-Datei nicht sicher gegen SQL-Injektionen waere, koennte ein potenzieller Angreifer dies um einiges leichter anhand der mysql_error() Ausgabe erkennen. Deswegen sollte man solche (mysql_error und aehnliches) in einer log-Datei speichern anstatt es dem Besucher zu zeigen, sofern man etwas im Internet veroeffentlicht. (In der Entwickelungsphase auf dem heimischen Computer ist das kein Problem, wenn der Programmierer selbst der einzige Besucher der Webseite ist.)

    Einmal editiert, zuletzt von SBIKA () aus folgendem Grund: "bei einem guten Programmierstil, wenn vorhanden". Satzstellung ein wenig verbessert, war nicht so gemeint wie geschrieben. ;)