Moin!
Ok hab jetzt mal glaube ich die beste Lösung dafür gefunden, da meine $m5 eh nur aus Zahlen besteht:
Nein.
MD5 erzeugt einen 16 Byte langen Hash, welcher oft als 32 Zeichen langer Hexadezimalstring ausgegeben wird. Es sind also mindestens die Buchstaben a-f in beliebiger Häufigkeit enthalten.
is_numeric() erlaubt zum Glück hexadezimale Zahlen, wenn sie ohne Vorzeichen sind, aber grundsätzlich hast du dich von Panik anstecken lassen.
mysql_real_escape_string() garantiert dir, dass egal was du hinein tust, am Ende ein sicherer String herauskommt, den du in Anführungszeichen in ein SQL-Statement integrieren kannst.
Dieser Code hier ist in der Sache fehlerhaft (die Diskussion, ob am Ende nicht trotzdem gültige Ergebnisse bei rauskommen, will ich nicht im Detail führen):
$md5 = mysql_real_escape_string(trim($_GET['id']));
if(!is_numeric($md5)) $md5 = md5(0);
1\. Du nimmst den URL-Parameter "id". Ok.
2\. trim()? Warum? Packst du zuviele Spaces in den Parameter, die du nicht brauchst? Das klingt etwas nach übertriebener Fehlerkorrektur dort, wo sie in der Sache nicht gerechtfertigt ist.
3\. Das getrimmte Ergebnis (alternativ: direkt die ID) wird durch mysql\_real\_escape\_string() so escaped, dass es direkt in einem SQL-String als quote-begrenzter String verwendet werden kann. Ok.
4\. Jetzt aber prüfst du, ob dieses escapte Ergebnis "numeric" ist. Falsche Stelle. WENN $\_GET['id'] numerisch war, könnte ja trotzdem das Escaping irgendein Zeichen verändert haben, so dass die is\_numeric-Prüfung jetzt irrtümlich fehlschlägt. Diese Prüfung kommt zum falschen Zeitpunkt. Prüfe immer die Originaldaten, die sich im Plaintext-Format befinden.
5\. Wenn is\_numeric() scheitert, erzeugst du einen neuen MD5-Wert von 0. Dieser Wert wird aber nicht escaped. Auch das ist grundsätzlich falsch.
Das Escaping einer spezialisierten Funktion zu überlassen versetzt dich in die Lage, dir selbst keine Gedanken mehr darüber machen zu müssen, ob irgendein Zeichen in deinem String konvertiert, escaped oder sonstwie verändert werden muss. Aber vor allem: Du kannst nicht wissen, ob sich die Liste der zu verändernden Zeichen nicht irgendwann mal ändert. Und du musst es auch nicht wissen, denn dafür gibts ja die Funktion.
Das aber bedeutet, dass du alle deine eigenen Prüffunktionen nur auf die Daten anwenden kannst, die sich als "plain text" in deinen Variablen befinden. Das sind alle die Strings, die nicht escaped wurden.
Alle Strings, die bereits escaped wurden, enthalten potentiell Zeichen, die nicht mehr der Standarddarstellung von "plain text" entsprechen. Deshalb kann man die Funktionen von PHP auf solche Strings nicht mehr anwenden, weil diese als Argument nur "plain text" akzeptieren. Diese Unterscheidung zu machen ist extrem wichtig, weil nur so die korrekte Trennung von "Prüf- und Korrekturphase der Daten" und "Verwendung und Escaping der Daten für den konkreten Kontext" geschehen kann.
Dein Code funktioniert technisch, weil alle Zeichen, die MD5 erzeugt, derzeit sowohl mit als auch ohne MySQL-Escaping identisch sind. Er ist aber sachlich falsch. Er birgt deshalb das Potential, technisch nicht mehr zu funktionieren, wenn du die hier programmierten Prinzipien identisch für einen anderen Datensachverhalt anwendest.
Korrekt wäre:
~~~php
// Standardbelegung der Variablen
$md5 = md5(0); // ist trotzdem fragwürdig, aber vielleicht inhaltlich ja gerechtfertigt
if (is_numeric($_GET['id'])) {
// Wenn die ID in der URL numerisch ist, dann nehmen wir diese
$md5 = $_GET['id'];
}
// SQL bauen, erst hier escapen!
$sql = 'SELECT whatever FROM table WHERE id = "'.mysql_real_escape_string($md5).'"';
Insbesondere der letzte Schritt ist wichtig: Du siehst hier, in dieser einzelnen Zeile, dass $md5 in jedem Fall dem notwendigen Escaping unterzogen wird. Das ist gut! Wenn du das Escaping aus der Zeile herausziehst und woanders reinschreibst, dann passiert technisch natürlich dasselbe. Aber du siehst nicht mehr auf den ersten Blick beim Betrachten der SQL-Zeile, ob für die Variable schon Escaping durchgeführt wurde:
$sql = 'SELECT whatever FROM table WHERE id = "'.$md5.'"';
Und das ist schlecht! Wenn man erst aufwendig weiteren Code lesen muss, um herauszufinden, ob eine Variable korrekt behandelt wurde, dann verursacht das Fehler - weil man die fehlerhaften Stellen nicht sofort erkennt oder unterscheiden kann von den korrekten Stellen.
- Sven Rautenberg