Sie machen %code% (wodurch alle %code% in %code% umgewandelt werden) und rufen dann %code% auf, was zu diesem Zeitpunkt nichts mehr erreichen wird, da keine Tags sind.
Es stimmt, aber dieses Maß an Flucht ist möglicherweise nicht in allen Fällen angemessen. Was, wenn Sie HTML in einer Datenbank speichern möchten?
Best Practices schreiben vor, dass Sie nicht flüchten sollten, wenn Sie Werte empfangen, wenn Sie sie anzeigen. Auf diese Weise können Sie die Anzeige von HTML-Code aus der Datenbank und von HTML-Code aus der Datenbank berücksichtigen, und diese Art von Code gehört auch wirklich dazu.
Ein weiterer Vorteil der Bereinigung ausgehender HTML besteht darin, dass ein neuer Angriffsvektor entdeckt werden kann. In diesem Fall wird das Bereinigen von eingehendem HTML nichts für Werte tun, die bereits in der Datenbank vorhanden sind, während die ausgehende Bereinigung rückwirkend angewendet wird Spezial
Beachten Sie auch, dass %code% in Ihrer ersten Funktion wahrscheinlich keine Auswirkungen hat, wenn alle %code% und %code% zu %code% und %code% geworden sind.
Um ehrlich zu sein, ich denke der Autor dieser Funktion hat keine Ahnung was XSS und SQL Injektionen sind oder was genau die verwendete Funktion macht.
Um nur zwei Kuriositäten zu nennen:
Außerdem: Im Allgemeinen sind Funktionen, die gegen XSS schützen, nicht geeignet, um SQL-Injektionen zu schützen und umgekehrt. Weil jede Sprache und jeder Kontext eigene Sonderzeichen hat, um die man sich kümmern muss.
Ich rate Ihnen zu erfahren, warum und wie Code-Injektion möglich ist und wie Sie dagegen vorbeugen können. Lerne die Sprachen, mit denen du arbeitest, insbesondere die Sonderzeichen und wie du ihnen entkommen kannst.
Bearbeiten Hier ist ein (wahrscheinlich seltsames) Beispiel: Stellen Sie sich vor, Sie erlauben Ihren Benutzern, einen Wert einzugeben, der als Pfadsegment in einem URI verwendet werden soll, den Sie in einem JavaScript-Code in einem% co_de verwenden % Attributwert. Der Sprachkontext sieht also so aus:
Und damit es mehr Spaß macht: Sie speichern diesen Eingabewert in einer Datenbank.
Um diesen Eingabewert nun korrekt in Ihrer Datenbank zu speichern, müssen Sie nur eine korrekte Codierung für den Kontext verwenden, in dem Sie diesen Wert in Ihre Datenbanksprache (d. h. SQL) einfügen möchten. der Rest spielt (noch) keine Rolle. Da Sie es in eine SQL-String-Deklaration einfügen möchten, sind die kontextabhängigen Sonderzeichen die Zeichen, mit denen Sie diesen Kontext ändern können. Wie bei Zeichenkettendeklarationen sind diese Zeichen (insbesondere) die Zeichen %code% , %code% und %code% , die maskiert werden müssen. Aber wie bereits gesagt, tun vorbereitete Aussagen alles, was für Sie funktioniert, also verwenden Sie sie.
Jetzt, da Sie den Wert in Ihrer Datenbank haben, möchten wir sie korrekt ausgeben. Hier gehen wir vom innersten zum äußersten Kontext über und wenden die richtige Kodierung in jedem Kontext an:
Jetzt alles zusammen:
%Vor%Wenn nun %code% ist %code% ist die Ausgabe:
%Vor%Aber die Verwendung all dieser Funktionen in diesen Kontexten ist kein Overkill. Obwohl die Kontexte ähnliche Sonderzeichen haben können, haben sie unterschiedliche Escape-Sequenzen. URI hat die sogenannte prozentuale Kodierung, JavaScript hat Escape-Sequenzen wie %code% und HTML hat Zeichenreferenzen wie %code% . Wenn Sie nicht nur eine dieser Funktionen verwenden, können Sie den Kontext unterbrechen.
Wenn Sie vorbereitete Anweisungen und SQL-Platzhalter verwenden und niemals Benutzereingaben direkt in Ihre SQL-Strings interpolieren, können Sie die SQL-Bereinigung vollständig überspringen.
Wenn Sie Platzhalter verwenden, wird die Struktur der SQL-Anweisung ( %code% ) getrennt von den Datenwerten, die (schließlich) an die Platzhalter gebunden sind, an die Datenbank-Engine gesendet. Dies bedeutet, dass, abgesehen von größeren Fehlern in der Datenbank-Engine, absolut keine Möglichkeit für die Datenwerte als SQL-Anweisungen missinterpretiert wird. Dies bietet vollständigen Schutz vor SQL-Injection-Angriffen, ohne dass Sie Ihren Fehler beheben müssen Daten für die Speicherung.
Nein, das ist nicht übertrieben, das ist eine Schwachstelle.
Dieser Code ist vollständig anfällig für SQL-Injection. Sie machen eine mysql_real_escape_string () und dann machen Sie eine stripslashes (). Ein %code% würde also nach mysql_real_escape_string () %code% werden und nach den stripslashes () wieder zu %code% zurückkehren. mysql_real_escape_string () allein ist am besten, um die sql-Injektion zu stoppen. Parametrisierte Abfragebibliotheken wie PDO und ADODB verwenden sie und parametrisierte Abfragen machen es sehr einfach, die SQL-Injektion vollständig zu stoppen.
Fahren Sie fort, testen Sie Ihren Code:
%Vor%Was wenn:
%Vor%Gepatcht:
%Vor%Dieser Code ist auch anfällig für einige Typen XSS:
%Vor%Was wenn:
%Vor%gepatcht:
%Vor%htmlspeicalchars codiert einfache und doppelte Anführungszeichen, stellen Sie sicher, dass die Variable, die Sie drucken, auch in Anführungszeichen eingeschlossen ist, dies macht es unmöglich, "auszubrechen" und Code auszuführen.
Nun, wenn Sie das Rad nicht neu erfinden wollen, können Sie HTMLPurifier verwenden. Es erlaubt Ihnen, genau zu entscheiden, was Sie wollen und was Sie nicht wollen und verhindert XSS-Angriffe und solche
Ich wundere mich über das Konzept der Hygienisierung. Sie sagen Mysql, genau das zu tun, was Sie tun sollen: Führen Sie eine Abfrageanweisung aus, die teilweise vom Benutzer der Website erstellt wurde. Sie konstruieren den Satz bereits dynamisch unter Verwendung der Benutzereingabe - Verketten von Zeichenfolgen mit Daten, die vom Benutzer bereitgestellt werden. Sie bekommen, wonach Sie fragen.
Wie auch immer, hier sind noch ein paar Desinfizierungsmethoden ...
1) Bei numerischen Werten sollten Sie zumindest vor oder während der Erstellung des Abfrage-Strings immer mindestens manuell umwandeln: "SELECT field1 FROM tblTest WHERE (id=". (int) $ val. ")";
2) Für Datumsangaben konvertieren Sie zuerst die Variable in den Unix-Zeitstempel. Verwenden Sie dann die Mysql FROM_UNIXTIME () -Funktion, um es zurück in ein Datum zu konvertieren. "SELECT field1 FROM tblTest WHERE (date_field & gt; = FROM_UNIXTIME (". Strtotime ($ val). ")". Dies wird manchmal benötigt, um MySQL zu interpretieren und zu speichern, die sich von den Script- oder OS-Layern unterscheiden / p>
3) Für kurze und vorhersehbare Zeichenfolgen, die einem bestimmten Standard (Benutzername, E-Mail, Telefonnummer usw.) entsprechen müssen, können Sie a) vorbereitete Anweisungen erstellen; oder b) Regex oder andere Datenvalidierung.
4) Für Strings, die keinem echten Standard folgen und überall vor und nach Entweichen oder ausführbaren Code (Text, Memos, Wiki-Markup, Links usw.) enthalten sein können oder nicht, können Sie das tun a) vorbereitete Aussagen machen; oder b) Speichern und Konvertieren von Binär- / Blob-Form - Konvertieren jedes Zeichens in Binär-, Hex- oder Dezimaldarstellung, bevor der Wert sogar an die Abfragezeichenfolge übergeben und beim Extrahieren zurückkonvertiert wird. Auf diese Weise können Sie sich mehr auf die HTML-Validierung konzentrieren, wenn Sie den gespeicherten Wert wieder ausgeben.
Es stimmt, aber dieses Maß an Flucht ist möglicherweise nicht in allen Fällen angemessen. Was, wenn Sie HTML in einer Datenbank speichern möchten?
Best Practices schreiben vor, dass Sie nicht flüchten sollten, wenn Sie Werte empfangen, wenn Sie sie anzeigen. Auf diese Weise können Sie die Anzeige von HTML-Code aus der Datenbank und von HTML-Code aus der Datenbank berücksichtigen, und diese Art von Code gehört auch wirklich dazu.
Ein weiterer Vorteil der Bereinigung ausgehender HTML besteht darin, dass ein neuer Angriffsvektor entdeckt werden kann. In diesem Fall wird das Bereinigen von eingehendem HTML nichts für Werte tun, die bereits in der Datenbank vorhanden sind, während die ausgehende Bereinigung rückwirkend angewendet wird Spezial
Beachten Sie auch, dass strip_tags
in Ihrer ersten Funktion wahrscheinlich keine Auswirkungen hat, wenn alle <
und >
zu <
und >
geworden sind.
Um ehrlich zu sein, ich denke der Autor dieser Funktion hat keine Ahnung was XSS und SQL Injektionen sind oder was genau die verwendete Funktion macht.
Um nur zwei Kuriositäten zu nennen:
stripslashes
nach mysql_real_escape_string
entfernt die Schrägstriche, die von mysql_real_escape_string
hinzugefügt wurden. htmlentities
ersetzt die Chatactors <
und >
, die in strip_tags
um Tags zu identifizieren. Außerdem: Im Allgemeinen sind Funktionen, die gegen XSS schützen, nicht geeignet, um SQL-Injektionen zu schützen und umgekehrt. Weil jede Sprache und jeder Kontext eigene Sonderzeichen hat, um die man sich kümmern muss.
Ich rate Ihnen zu erfahren, warum und wie Code-Injektion möglich ist und wie Sie dagegen vorbeugen können. Lerne die Sprachen, mit denen du arbeitest, insbesondere die Sonderzeichen und wie du ihnen entkommen kannst.
Bearbeiten Hier ist ein (wahrscheinlich seltsames) Beispiel: Stellen Sie sich vor, Sie erlauben Ihren Benutzern, einen Wert einzugeben, der als Pfadsegment in einem URI verwendet werden soll, den Sie in einem JavaScript-Code in einem% co_de verwenden % Attributwert. Der Sprachkontext sieht also so aus:
Und damit es mehr Spaß macht: Sie speichern diesen Eingabewert in einer Datenbank.
Um diesen Eingabewert nun korrekt in Ihrer Datenbank zu speichern, müssen Sie nur eine korrekte Codierung für den Kontext verwenden, in dem Sie diesen Wert in Ihre Datenbanksprache (d. h. SQL) einfügen möchten. der Rest spielt (noch) keine Rolle. Da Sie es in eine SQL-String-Deklaration einfügen möchten, sind die kontextabhängigen Sonderzeichen die Zeichen, mit denen Sie diesen Kontext ändern können. Wie bei Zeichenkettendeklarationen sind diese Zeichen (insbesondere) die Zeichen onclick
, "
und '
, die maskiert werden müssen. Aber wie bereits gesagt, tun vorbereitete Aussagen alles, was für Sie funktioniert, also verwenden Sie sie.
Jetzt, da Sie den Wert in Ihrer Datenbank haben, möchten wir sie korrekt ausgeben. Hier gehen wir vom innersten zum äußersten Kontext über und wenden die richtige Kodierung in jedem Kontext an:
\
(das aktuelle Pfadsegment lassen), /
und ?
(beide verlassen den URI-Pfadkontext). Wir können dafür #
verwenden. rawurlencode
, "
und '
kümmern. Wir können dafür \
verwenden (falls verfügbar). json_encode
, &
, "
und '
achten. Wir können hierfür <
verwenden. Jetzt alles zusammen:
%Vor% Wenn nun htmlspecialchars
ist $row['user-input']
ist die Ausgabe:
Aber die Verwendung all dieser Funktionen in diesen Kontexten ist kein Overkill. Obwohl die Kontexte ähnliche Sonderzeichen haben können, haben sie unterschiedliche Escape-Sequenzen. URI hat die sogenannte prozentuale Kodierung, JavaScript hat Escape-Sequenzen wie "bar/baz"
und HTML hat Zeichenreferenzen wie \"
. Wenn Sie nicht nur eine dieser Funktionen verwenden, können Sie den Kontext unterbrechen.
Sie machen htmlentities
(wodurch alle >
in >
umgewandelt werden) und rufen dann strip_tags
auf, was zu diesem Zeitpunkt nichts mehr erreichen wird, da keine Tags sind.
Wenn Sie vorbereitete Anweisungen und SQL-Platzhalter verwenden und niemals Benutzereingaben direkt in Ihre SQL-Strings interpolieren, können Sie die SQL-Bereinigung vollständig überspringen.
Wenn Sie Platzhalter verwenden, wird die Struktur der SQL-Anweisung ( SELECT foo, bar, baz FROM my_table WHERE id = ?
) getrennt von den Datenwerten, die (schließlich) an die Platzhalter gebunden sind, an die Datenbank-Engine gesendet. Dies bedeutet, dass, abgesehen von größeren Fehlern in der Datenbank-Engine, absolut keine Möglichkeit für die Datenwerte als SQL-Anweisungen missinterpretiert wird. Dies bietet vollständigen Schutz vor SQL-Injection-Angriffen, ohne dass Sie Ihren Fehler beheben müssen Daten für die Speicherung.
Nein, das ist nicht übertrieben, das ist eine Schwachstelle.
Dieser Code ist vollständig anfällig für SQL-Injection. Sie machen eine mysql_real_escape_string () und dann machen Sie eine stripslashes (). Ein "
würde also nach mysql_real_escape_string () \"
werden und nach den stripslashes () wieder zu "
zurückkehren. mysql_real_escape_string () allein ist am besten, um die sql-Injektion zu stoppen. Parametrisierte Abfragebibliotheken wie PDO und ADODB verwenden sie und parametrisierte Abfragen machen es sehr einfach, die SQL-Injektion vollständig zu stoppen.
Fahren Sie fort, testen Sie Ihren Code:
%Vor%Was wenn:
%Vor%Gepatcht:
%Vor%Dieser Code ist auch anfällig für einige Typen XSS:
%Vor%Was wenn:
%Vor%gepatcht:
%Vor%htmlspeicalchars codiert einfache und doppelte Anführungszeichen, stellen Sie sicher, dass die Variable, die Sie drucken, auch in Anführungszeichen eingeschlossen ist, dies macht es unmöglich, "auszubrechen" und Code auszuführen.
Nun, wenn Sie das Rad nicht neu erfinden wollen, können Sie HTMLPurifier verwenden. Es erlaubt Ihnen, genau zu entscheiden, was Sie wollen und was Sie nicht wollen und verhindert XSS-Angriffe und solche
Ich wundere mich über das Konzept der Hygienisierung. Sie sagen Mysql, genau das zu tun, was Sie tun sollen: Führen Sie eine Abfrageanweisung aus, die teilweise vom Benutzer der Website erstellt wurde. Sie konstruieren den Satz bereits dynamisch unter Verwendung der Benutzereingabe - Verketten von Zeichenfolgen mit Daten, die vom Benutzer bereitgestellt werden. Sie bekommen, wonach Sie fragen.
Wie auch immer, hier sind noch ein paar Desinfizierungsmethoden ...
1) Bei numerischen Werten sollten Sie zumindest vor oder während der Erstellung des Abfrage-Strings immer mindestens manuell umwandeln: "SELECT field1 FROM tblTest WHERE (id=". (int) $ val. ")";
2) Für Datumsangaben konvertieren Sie zuerst die Variable in den Unix-Zeitstempel. Verwenden Sie dann die Mysql FROM_UNIXTIME () -Funktion, um es zurück in ein Datum zu konvertieren. "SELECT field1 FROM tblTest WHERE (date_field & gt; = FROM_UNIXTIME (". Strtotime ($ val). ")". Dies wird manchmal benötigt, um MySQL zu interpretieren und zu speichern, die sich von den Script- oder OS-Layern unterscheiden / p>
3) Für kurze und vorhersehbare Zeichenfolgen, die einem bestimmten Standard (Benutzername, E-Mail, Telefonnummer usw.) entsprechen müssen, können Sie a) vorbereitete Anweisungen erstellen; oder b) Regex oder andere Datenvalidierung.
4) Für Strings, die keinem echten Standard folgen und überall vor und nach Entweichen oder ausführbaren Code (Text, Memos, Wiki-Markup, Links usw.) enthalten sein können oder nicht, können Sie das tun a) vorbereitete Aussagen machen; oder b) Speichern und Konvertieren von Binär- / Blob-Form - Konvertieren jedes Zeichens in Binär-, Hex- oder Dezimaldarstellung, bevor der Wert sogar an die Abfragezeichenfolge übergeben und beim Extrahieren zurückkonvertiert wird. Auf diese Weise können Sie sich mehr auf die HTML-Validierung konzentrieren, wenn Sie den gespeicherten Wert wieder ausgeben.