Tach!
Und du meinst nun, weil sie aus der DB kommen, sind die Daten "sicher"?
Naja wenn sie maskiert/codiert eingefügt wurden?
Du hast es anscheinend immer noch nicht verstanden. Maskiert/codiert wofür? Es gibt keine "Mach-alles-Böse-raus-Maskierung". Für SQL müssen vor allem Anführungszeichen umgeschrieben werden, aber < und > sind da harmlos und bleiben wie sie sind. Für HTML müssen diese beiden aber umgeschrieben werden und Anführungszeichen müssen nicht mit Backslash ergänzt sondern als " geschrieben werden (nicht in jedem Fall, aber in Attributen).
Das verstehe ich wohl aber ich will ja verhindern das ein < oder ähnliches in die Datenbank kommt.
Warum willst du das verhindern? Was hat das Zeichen denn verbrochen? Man kann auch mit allen anderen harmlos scheinenden Zeichen Unsinn anstellen, indem Nutzer zum Beispiel Texte verfassen, die man als Betreiber nicht haben möchte (Spam, etc.).
Warum sollte man Markup in einer DB speichern?
Das kommt doch auf den Anwendungsfall an. Manchmal will man das, manchmal nicht. Hier im Forum ist es Sinn und Zweck, dass Anweder HTML eingeben, das auch in der Datenbank zu liegen kommt. Nur muss es beim Ausgaben an den Browser so maskiert sein, dass der das nicht als HTML interpretiert, sondern als Zeichen, die anzuzeigen sind.
Natürlich gehe ich von meinem einfachen Fall aus und es ist interessant das einem noch viel mehr Möglichkeiten zu Verfügung stehen bei denen man dann auch einiges beachten muss. Nur ich sehe im Moment nicht die Notwendigkeit mir alles aneignen zu müssen was möglich und erst damit nötig ist.
Wichtig ist vor allem, das Prinzip zu verstehen. Alle Einzelheiten, besonders die in der Fortsetzung muss man sich nicht merken, das kann man auch erst bei Bedarf nachschlagen. Aber man muss erkennen, wann der Bedarf da ist. Und deshalb ist wenigstens eine allgemeine Sensibilisierung für das Thema wichtig.
Also Wenn zum Beispiel:
if(isset($_POST['chat']) && !empty($_POST['chat'])) { $writer = mysqli_real_escape_string($_SESSION['user_name']); $chat = mysqli_real_escape_string($_POST['chat']); $insert_message = sprintf( 'INSERT INTO chat (' . 'message_writer, message, message_date' . ') VALUES (' . '\'%1$s\', \'%2$s\', \'%3$s\'' . ')', $_SESSION['user_name'], $_POST['chat'], time()); if($db -> query($insert_message) === TRUE) { $db -> commit(); } else { //error_log! $create_db_connect->error. } exit(); }
Und in der
$_POST['chat']
steht meinetwegen <script>böser.pfad</script>, was kommt in der Datenbank an?
In der Datenbank kommt <script>böser.pfad</script> an. In dem Text kommt kein Zeichen vor, das im SQL-Statement eine Sonderbedeutung hat.
Aber anscheinend ist dir nicht einmal aufgefallen, dass du zwar schön maskiert hast, aber die Ergebnisse in Variablen ablegst, die du dann gar nicht verwendest. Also genauer gesagt: du hast gar nichts maskiert und eine potentielle SQL-Injection-Lücke. Mit dem Prinzip Maskieren beim Übergang in den anderen Kontext wäre das nicht passiert. Du hast da grad selbst ein schönes Beispiel geliefert, warum man nicht schon vorher, sondern genau zum richtigen Zeitpunkt die Maskierung vornehmen sollte.
$insert_message = sprintf(
"INSERT INTO chat ("
. "message_writer, message, message_date"
. ") VALUES ("
. "'%s', '%s', %s"
. ")",
mysqli_real_escape_string($_SESSION['user_name']),
mysqli_real_escape_string($_POST['chat']),
time());
time() liefert übrigens ausnahmslos einen Zahlenwert. Der braucht nicht maskiert zu werden und der braucht auch keine Anführungszeichen im Statement. Außerdem habe ich die Positionsangaben in den Platzhaltern weggelassen (nur %s statt %1$s), weil sie in diesem Fall keinen Nutzen bringen. Die Reihenfolge der Parameter ist immer exakt gleich und ändert sich nicht, wie beispielsweise bei Übersetzungen in andere Spachen mit anderen Grammatiken und Reihenfolgen im Satz.
Nochmal zum Inhalt von $_POST['chat']
. Um das SQL unbeabsichtigt umzugestalten, musst du einen Text mit einfachem Anführungszeichen drin übergeben. Ohne Escaping würde an der Stelle der Wert zu Ende sein und alles weitere würde als Code angesehen werden. Für das SQL müssen lediglich diese Zeichen berücksichtigt werden und nicht irgendwelche mit besonderer Bedeutung im HTML-Kontext. Die Datenbank hat keine Ahnung, in welchem Kontext später mal ihr Inhalt landen soll und deshalb kann sie dafür auch keine Entschärfungen vornehmen.
Und wieso entschärft:
?> <time datetime="<?php echo date('c', $row['message_date']); ?>"><?php echo date('H:i:s', $row['message_date']); ?></time> <span class="author"><?php echo htmlspecialchars($row['message_writer']); ?></span> </footer> <p class="message"><?php echo htmlspecialchars($row['message']); ?></p>
das nicht die Ausgabe?
Doch, das "entschärft" die Ausgabe. Hier ist es genauso gemacht, wie es sein sollte: beim Übergang in den HTML-Kontext, nicht eher und auch nicht wirkungslos, weil im nicht vorhandenen "eher" nun kein Fehler mehr stecken kann.
Mit deinem Beispiel von vorhin <script>böser.pfad</script> würde das genauso auf dem Bildschirm zu stehen kommen und nicht vom Browser als Code interpretiert werden.
Dass diese Ausgabe trotzdem unerwünscht ist, ist nicht das Problem fehlender Maskierungen, sondern nur eins, das mit Moderation gelöst werden muss. Diese und andere Inhalte unangenehmer Zeitgenossen musst du händisch entfernen. Technische Lösungen können in Einzelfällen helfen, aber dann kommt die nächste Spamwelle mit anderen Inhalten und umgeht deine Maßnahmen wieder.
Ich glaube mehr will ich überhaupt nicht. Also mir würde kein Beispiel einfallen wo ich etwas anderes machen möchte. Bzw. doch, eigentlich schon, vorher würde gern noch prüfen ob etwas derartiges in dem Formularfeld steht und dann die weiterleitung direkt unterbinden.
Du kannst sicher eine Regel definieren, mit der "derartiges" erkannt werden kann. Aber was ist mit "andersartigem"?
Oder zumindest wenn nicht das drin steht was ich erwarte dann eben die weiterleitung unterbinden. Sprich, wenn ich in dem Formularfeld eine Zahl erwarte, dann hat das gefälligst auch eine zahl zu sein und kein String. Aber das ist Javascript, dass hab ich zwar schon irgendwo gefunden, aber mich noch nicht mit beschäftigt.
Nicht unbedingt. HTML5 und moderne Browser kennen auch <input type="number">. Aber nur weil du sowas in dein HTML einbaust, heißt das noch lange nicht, dass man nur noch moderne Browser einsetzen kann und die das für dich verhindern. Oder wenn es denn eine Javascript-Lösung sein soll, dann können auch nur Browser mit eingeschaltetem Javascript Fehleingaben verhindern. Spam-Bots, die ihre HTML-Requests zu Fuß zusammenbauen und abschicken, interessieren sich nicht dafür, dass du sie gebeten hast, nur Zahlen zu liefern. Die schicken dir trotzdem ihren Müll zu. Den kannst du nur serverseitig erkennen und aussortieren. Bei Zahlen oder Werten aus einer vorher definierten Liste geht das noch einfach, bei Freitext wird es herausfordernder bis unmöglich, alles Ungewünschte zu erkennen.
dedlfix.