Sicherheit bei MySQLi abfrage


Loddar1

Erfahrenes Mitglied
#1
Guten Morgen,
es gibt immer wieder die Hinweise auf Sicherheit deshalb mal eine Frage.
Wenn ich eine Datenbankabfrage mache reicht dann diese Sicherheit oder muß ich da noch mehr tun?
PHP:
$usermail = strip_tags($_REQUEST['email']);
$usermail = htmlentities($usermail, ENT_QUOTES | ENT_HTML5);
$usermail = $mysqli->real_escape_string(trim($usermail));
$benutzer = strip_tags($_REQUEST['benutzer']);
$benutzer = $mysqli->real_escape_string($benutzer);
.....
$sql="SELECT * FROM tbname  WHERE username = '$benutzer' AND mail = '$usermail'";
Ist da vielleicht was überflüssig?

MySQLi Objekt orientiert php 7.2
kann mir jemand einen Tipp geben?

Danke im voraus Loddar1
 

ComFreek

Mod | @comfreek
Moderator
#2
strip_tags($_REQUEST['email']); $usermail = htmlentities($usermail, ENT_QUOTES | ENT_HTML5);
Nicht nur überflüssig, sondern auch falsch.

strip_tags($_REQUEST['benutzer']);
Auch überflüssig und falsch.

Deine real_escape_string Aufrufe sind ok, viel besser wären aber Prepared Statements.

Zu diesem Thema habe ich schon öfters was geschrieben, z. B. hier: SQL Injection Diskussion zu "MySQL Rückgabewert inkorrekt"

(Vllt. wäre es mal gut einen Referenzartikel für Kontexthandling zu schreiben, was dann MySQL/HTML/Regex Injections und auch so semantisch falsche Dinge wie im OP behandeln würde. Mag jemand mithelfen? ;))
 

Loddar1

Erfahrenes Mitglied
#3
Danke für die Antwort,
aber falsch und überflüssig verstehe ich nicht.
Ich dachte das die real_escape_string Aufrufe falsch sind.
Die Prepared Statements verstehe ich auch nicht wirklich, das dauert wohl noch.
 

ComFreek

Mod | @comfreek
Moderator
#4
aber falsch und überflüssig verstehe ich nicht.
Weil du nun die Daten in der DB nicht in Reinform gespeichert hast.

Zum Beispiel bei strip_tags entfernst du sogar bestimmte Zeichen. Was, wenn diese Zeichen Teil der echten Eingabe waren? Du magst bei E-Mail-Adressen vielleicht noch recht haben, dass sie sowieso keine <> Zeichen enthalten dürfen*, aber i. Allg. stimmt das nicht für andere Nutzereingaben wie z. B. Blogtexte.

Der andere Punkt ist, dass du Probleme bei der Ausgabe später bekommst. Was ist, wenn du später die E-Mail Adresse im JSON-Format ausgeben willst? Geht nicht. Zumindest nicht einfach. Denn nun hast du htmlentities drübergeworfen und hast nun HTML-Entities drin (&amp; zum Beispiel). Es geht nur dann gut, wenn du deine Daten als HTML ausgeben möchtest, aber auch nur dann wenn es UTF8-kodiertes HTML5 ist, denn das sind die Flags, die du htmlentities (UTF8 standardmäßig) übergeben hast.

Ich hoffe, dass beide Punkte genug motivieren, Daten möglichst in Reinform in der DB zu speichern, ohne Annahmen über den Ausgabekontext zu treffen. Wende Transformationen und Escaping der Sicherheit wegen immer erst zur Zeit der Ausgabe an!

Die Prepared Statements verstehe ich auch nicht wirklich, das dauert wohl noch.
Dazu gibt es genug Tutorials im Internet, einfach mal suchen. Am besten auf offiziellen Dokumentationsseiten der "Hersteller" wie PHP selbst.

Ich dachte das die real_escape_string Aufrufe falsch sind.
Warum? Prepared Statements sind zwar wesentlich besser -- semantisch gesehen, aber real_escape_string sollte wohl schon auch gehen.

Nachdem du Prepared Statements verstanden hast, empfehle ich dir meinen Beitrag SQL Injection Diskussion zu "MySQL Rückgabewert inkorrekt" durchzulesen, denn auch trotz Prepared Statements kann man Sicherheitslücken reinprogrammieren!

*) google mal nach "email validate regex" :D E-Mail Adressen sind wahnsinnig kompliziert.