-
29. 01. 2012, 14:13 #1
[PHP] Strings vergleichen / Charset Problem?
Hallo zusammen,
ich habe folgendes Script gebastelt:
In eine mySQL-Datenbank speichere ich eine URL und einen bestimmten Teil des Quellcodes (der von dieser URL ist) ein.
Nun möchte ich, dass er überprüft, ob dieser Teil des Quellcodes irgendwo im gesamten Quellcode der URL vorkommt.
Dafür habe für den Vergleich folgende Funktion geschrieben:
Um den Quellcode in die Datenbank zu speichern, benutzte ichPHP-Code:function check($id) {
$sql_select = mysql_query("SELECT url, text FROM vergleich WHERE id = ".$id."");
$num_rows = mysql_num_rows($sql_select);
if(empty($num_rows)) {
$ausgabe = "Datensatz wurde nicht gefunden";
} else {
while($row = mysql_fetch_array($sql_select)) {
$quelltext = @file_get_contents($row["url"]);
if (strpos(htmlentities(preg_replace('/\s\s+/', ' ',$quelltext)), preg_replace('/\s\s+/', ' ',stripslashes($row["text"])) ) !== false) {
$ausgabe = "Ok";
} else {
$ausgabe = "Fehler";
}
}
}
return "ID " . $id . ": " . $ausgabe;
}
Wenn ich nach dem Eintragen direkt die Funktion aufrufe, dann bekomme ich als Meldung "Ok".PHP-Code:$text = mysql_real_escape_string(htmlentities($_POST["text"]));
Nun hab ich aber auch noch ein Formular gebastelt, mit dem ich die Datenbankeinträge (URL, Quellcode) ändern kann.
Wenn ich dort keine Änderungen vornehme, sondern nur auf speichern klicke und danach die Funktion wieder aufrufe, dann bekomme ich "Fehler" ausgegeben, obwohl ja eigentlich keine Änderungen vorgenommen wurde.
Beim bearbeiten, muss der Quellcode anscheinend verändert worden sein, ohne das man dies optisch wahrnehmen kann. Vermutlich liegt es an den Charset, der irgendwie verändert wird.
Alle Seiten haben die Kodierung "UTF-8 ohne BOM" und im Header der Seite habe ich ebenfalls das Charset UTF8 angegeben.
Das Bearbeiten-Formular ist genauso aufgebaut, wie das Formular zum eintragen. Dort verwende ich stripslashes($text) um mir den Quellcode in einer Textarea anzeigen zu lassen und zum einspeichern verwende ich wie oben mysql_real_escape_string und htmlentities.
Kann es eventuell auch hier zu einem Problem kommen, weil ich ja schon einmal htmlentities benutzt habe?
Ich hoffe ihr versteht mein Problem und könnt mir weiterhelfen.
Gruß,
DerEine
-
29. 01. 2012, 16:34 #2
Re: [PHP] Strings vergleichen / Charset Problem?
Ich habe da Verständnisprobleme. Wozu sind überhaupt diese stripslashes- und htmlentities-Aufrufe gut? Korrekt wäre stripslashes nur, wenn magic_quotes_gpc (trotz Missbilligung) aktiviert ist und Daten aus den GET-/POST-/COOKIE-Arrays kommen oder wenn magic_quotes_runtime aktiviert ist. Das müsste man folglich prüfen, wenn der Code nicht gerade nur mit magic_quotes_gpc/magic_quotes_runtime korrekt funktionieren soll. htmlentities ist generell kaum sinnvoll, ich habe es IIRC noch nie benötigt. Nötig wäre hingegen htmlspecialchars und das dann aber auch nur genau immer dann, wenn Text in einem HTML-Kontext ausgegeben werden soll. Dort verwendest du aber offenbar nur stripslashes, was maximal zusätzlich nötig wäre, aber eben nicht ausreicht, da sonst XSS möglich wird. Nicht nötig ist htmlspecialchars oder gar htmlentities hingegen bei dem Eintrag in eine Datenbank, dort ist (bei einem String und Nutzung von MySQL) nur mysql_real_escape_string nötig.
Auch sonst st der Code recht seltsam. Wozu durchläufst du die while-Schleife möglicherweise mehrfach, wenn du eh immer nur das letzte Ergebnis auswertest? Das sorgt doch nur für unnötige(?) und möglicherweise sogar identische Anfragen an den Server.
-
29. 01. 2012, 17:15 #3
Re: [PHP] Strings vergleichen / Charset Problem?
Auf dem Webserver ist leider magic_quotes_gpc aktiviert, deshalb nehme ich für das Auslesen in eine Textarea stripslashes, damit die überflüssigen Zeichen entfernt werden und nicht den Quelltext (der aus der Datenbank ausgelesen wird) verunreinigen.
Für das speichern des Quelltextes muss ich also nur mysql_real_escape_string verwenden?
Sehe ich das richtig, dass wenn ich in der Funktion den Quelltext, welchen ich mir über die URL hole, mit dem Quelltext aus der Datenbank vergleiche auch kein htmlspecialchars benötige?
Ich habe mit htmlspecialchars/htmlentities gearbeitet, weil die Strings nie korrekt vergleichen wurden wenn dort Umlaute bzw. Sonderzeichen enthalten waren.
Die Schleife in der Funktion ist natürlich fehl am Platz und resultiert daraus, dass ich zuerst eine Funktion basteln wollte, welche direkt alle Datenbankeinträge überprüft. Ich habe vergessen die Schleife zu entfernen.
Gruß,
DerEine
Edit:
Ich habe jetzt mal alles so weit bereinigt und htmlspecialchars bzw. htmlentities entfernt. Die Situation ist immer noch wie oben beschrieben:
Wenn ich den Link und den Quelltext einspeicher und überprüfe, bekomme ich "Ok". Wenn ich nun allerdings im Bearbeiten-Formular auf Speichern klicke, ohne das ich etwas geändert habe, bekomme ich bei der nächsten Überprüfung "Fehler" ausgegeben.
Woran kann das liegen?Geändert von DerEine (29. 01. 2012 um 17:27 Uhr)
-
29. 01. 2012, 18:37 #4
Re: [PHP] Strings vergleichen / Charset Problem?
Du meinst wohl eher die zur Verarbeitung der nach dem Absenden des Formulars übermittelten Daten? Dort wäre das dann nämlich tatsächlich nötig, auch wenn ich davon abrate, das so pauschal anzuwenden. Was ist, wenn die Serverkonfiguration diesbezüglich geändert wird?
Auf aus der Datenbank gelesene Daten dürfte magic_quotes_gpc keinen Einfluss haben. Meinst du vielleicht magic_quotes_runtime?damit die überflüssigen Zeichen entfernt werden und nicht den Quelltext (der aus der Datenbank ausgelesen wird) verunreinigen.
Ja, wenn du den String als Teil eines MySQL-Abfragestrings verwenden willst, dann musst du das tun. Wie kommst du auf die Idee, dass noch weitere Umwandlungen nötig wären und wie begründest du dann die von dir gewählte Reihenfolge? Beachte, dass eine zusätzliche unpassende Maskierung in der falschen Reihenfolge ggf. sogar Schwachstellen aufreißen kann.Für das speichern des Quelltextes muss ich also nur mysql_real_escape_string verwenden?
Nein, da du für den Vergleich die Strings nicht in einem HTML-Kontext ausgeben musst.Sehe ich das richtig, dass wenn ich in der Funktion den Quelltext, welchen ich mir über die URL hole, mit dem Quelltext aus der Datenbank vergleiche auch kein htmlspecialchars benötige?
Dann wurden aber offenbar verschiedene Kodierungen verwendet. Dagegen hilft auch keine Maskierung, die maskierten Strings müssen ja ebenfalls unterschiedlich sein, denn das Entfernen der Maskierung muss ja wieder die jeweiligen Ursprungsstrings erzeugen.Ich habe mit htmlspecialchars/htmlentities gearbeitet, weil die Strings nie korrekt vergleichen wurden wenn dort Umlaute bzw. Sonderzeichen enthalten waren.
Ohne den entsprechenden Code zu kennen: Irgendetwas machst du offenbar bei der Ausgabe in dem HTML-Dokument oder bei dem Eintragen in die Datenbank noch falsch. Korrekt wäre htmlspecialchars bei der Ausgabe und mysql_real_escape_string bei dem Aktualisieren in die Datenbank. Wenn du auf dem Weg den Fehler nicht findest, solltest du vielleicht einfach mal die Strings vergleichen. Durch den Unterschied kann man ja ggf. auf den Fehler schließen.Wenn ich den Link und den Quelltext einspeicher und überprüfe, bekomme ich "Ok". Wenn ich nun allerdings im Bearbeiten-Formular auf Speichern klicke, ohne das ich etwas geändert habe, bekomme ich bei der nächsten Überprüfung "Fehler" ausgegeben.
Woran kann das liegen?
Allgemein solltest du dir klar machen, welche Maskierungen wann in welcher Reihenfolge zu verwenden sind. So wie du sie bisher verwendet hast, ist dir das offenbar nicht bewusst. Eigentlich ist es aber ganz einfach. Man muss nur überlegen, in welcher Art ein String vorliegt. Sofern er in einer anderen Form benötigt wird, wendet man nacheinander die Funktionen zum Demaskieren an und zwar in der umgekehrten Reihenfolge zu der, die bei der Maskierung genutzt wurde. Den nun unmaskierten String maskiert man anschließend in der tatsächlich benötigten Art. Die tatsächlich benötigte Maskierung ergibt sich daraus, dass die unmaskierten Daten Zeichen enthalten könnten, die in dem zu nutzenden Kontext eine unerwünschte Wirkung haben könnten und die Maskierung genau diese Zeichen entschärft.
-
29. 01. 2012, 20:22 #5
Re: [PHP] Strings vergleichen / Charset Problem?
Danke das hat mir weiter geholfen und soweit scheint es zu funktionieren.
Zum einspeichern, habe ich jetzt immer mysql_real_escape_string genommen. Für das Auslesen im Bearbeiten-Formular habe ich jetzt stripslashes(htmlspecialchars($text)) genommen. Auch nachdem ich dort auf Speichern geklickt habe, bekomme ich ein "Ok" bei der Prüfung ausgegeben. Also so, wie es sein sollte.
In der Funktion habe ich noch ein htmlspecialchars vor $row["text"] eingefügt, sodass nun alles seine Richtigkeit haben müsste.
In der mySQL Datenbank wird mir nach dem Eintragen und auch nach dem Bearbeiten der Quellcode z.B. so angezeigt:
HTML-Code:<div class=\"section\" id=\"top\">
Ein Problem habe ich allerdings noch.
Im Eintragen-Formular habe ich die Möglichkeit automatisch den gesamten Quelltext der URL zu speichern. Dies mache ich wie folgt:
Die Prüfung nach der Eingabe sagt "Ok".PHP-Code:$quelltext = @file_get_contents($_POST["url"]);
$text = mysql_real_escape_string($quelltext);
In der Datenbank steht nun:
Gehe ich nun wieder in das Bearbeiten-Formular und drück auf speichern, bekomme ich "Fehler" ausgegeben. In der Datenbank hat sich der Quelltext nun geändert:HTML-Code:<div class="section" id="header">
Da beim ersten Eintragen kein POST übergeben wird, wenn ich den gesamten Quelltext übernehme, habe ich auch nicht die Escape-Zeichen.HTML-Code:<div class=\"section\" id=\"top\">
Meine Frage ist: Warum sagt er mir beim Eintragen, dass alles "Ok" ist (wir haben keine Escape-Zeichen) und nach dem Bearbeiten, wenn durch die POST-Übergabe Escape-Zeichen hinzugefügt wurden, dass die Prüfung fehlerhaft ist?
Was mir gerade noch auffällt. Wenn ich manuell den gesamten Quelltext der URL kopiere und in die Datenbank speicher, bekomme ich direkt "Fehler" ausgegeben. Wenn ich den gesamten Quellcode selbstständig einspeicher haben wir ja theoretisch den Schritt (bzw. den Quellcode) so wie er nach dem Bearbeiten ist (eben mit den Escape-Zeichen).
-
29. 01. 2012, 20:49 #6
Re: [PHP] Strings vergleichen / Charset Problem?
Diese Reihenfolge ist falsch, da du wie erwähnt erst die Maskierungen entfernen musst, um den korrekten String zu erhalten, bevor du ihn dem Kontext entsprechend neu maskieren kannst. Durch das vorgezogene htmlspecialchars wird aus einem " (das wegen dem magic_quotes_gpc zu \" verfälscht ist) zu einem \". In der korrekten, umgekehrten Reihenfolge würde sich nur " ergeben.
In welcher Funktion? In dem Substring-Vergleich in der Funktion check ist htmlspecialchars nicht sinnvoll, da dort eben keine Ausgabe des Strings in einem HTML-Kontext erfolgt. Wenn du es unsinnigerweise dennoch nutzen willst, müsstest du es auf beide Strings anwenden.In der Funktion habe ich noch ein htmlspecialchars vor $row["text"] eingefügt, sodass nun alles seine Richtigkeit haben müsste.
Das liegt wohl wie in dem obigen Fall an der falschen Reihenfolge oder dem Vergessen von stripslashes. Die Slashes sollen dort ja vermutlich zumindest nicht stehen, oder?In der mySQL Datenbank wird mir nach dem Eintragen und auch nach dem Bearbeiten der Quellcode z.B. so angezeigt:
HTML-Code:<div class=\"section\" id=\"top\">
Ich kann bei deiner Erklärung dazu nicht folgen, aber dass die fälschlich hinzugefügten (bzw. nicht von dir entfernten) Slashes das Ergebnis beeinflussen können, ist ja kaum verwunderlich. Insbesondere wenn der Vergleichsstring ein Anführungszeichen enthält.Warum sagt er mir beim Eintragen, dass alles "Ok" ist (wir haben keine Escape-Zeichen) und nach dem Bearbeiten, wenn durch die POST-Übergabe Escape-Zeichen hinzugefügt wurden, dass die Prüfung fehlerhaft ist?
Auch das deutet darauf hin, dass du die Verfälschungen von magic_quotes_gpc nicht korrekt kompensierst.Was mir gerade noch auffällt. Wenn ich manuell den gesamten Quelltext der URL kopiere und in die Datenbank speicher, bekomme ich direkt "Fehler" ausgegeben. Wenn ich den gesamten Quellcode selbstständig einspeicher haben wir ja theoretisch den Schritt (bzw. den Quellcode) so wie er nach dem Bearbeiten ist (eben mit den Escape-Zeichen).
Ich kann dir nur erneut nahelegen, den Zweck der Maskierungen zu verstehen, denn ich habe weiterhin den Eindruck, dass er dir unklar ist oder du etwas falsch verstanden hast. Eventuell trägt es zum Verständnis bei, dass die durch magic_quotes_gpc und magic_quotes_runtime automatisch durchgeführten Maskierungen *nicht* sinnvoll sind, weil sie ohne Berücksichtigung des Kontexts erfolgen und in den meisten Fällen *vor* jeder weiteren Verarbeitung der Strings rückgängig gemacht werden müssen.
-


Zitieren

mehr lesen...







Occupy Kiel: Massiver Sachschaden...
Heute, 20:15 in gulli:news