Halten Sie htmlspecialchars und mysql_real_escape_string mein PHP-Code zum Schutz vor Injektion?

StackOverflow https://stackoverflow.com/questions/110575

Frage

Bereits heute Morgen eine Frage gefragt wurde, in Bezug auf Eingabevalidierung Strategien in Web-Apps .

Die Top-Antwort, zum Zeitpunkt des Schreibens, schlägt in PHP nur htmlspecialchars und mysql_real_escape_string verwenden.

Meine Frage lautet: Ist das immer genug? Gibt es mehr sollten wir wissen? Wo brechen diese Funktionen nach unten?

War es hilfreich?

Lösung

Wenn es um Datenbankabfragen kommt, immer versuchen, und bereit parametrisiert Abfragen zu verwenden. Die mysqli und PDO Bibliotheken unterstützen diese. Dies ist unendlich sicherer als entweichende Funktionen wie mysql_real_escape_string.

Ja, das ist mysql_real_escape_string effektiv nur eine Zeichenfolge zu entkommen Funktion. Es ist kein Wundermittel. Alles, was es tun wird, ist gefährlich Zeichen, um zu entkommen, dass sie sicher sein können in einem einzigen Abfrage-String zu verwenden. Wenn Sie jedoch nicht Ihre Eingaben vorher sanieren, dann werden Sie anfällig für bestimmte Angriffsvektoren sein.

Stellen Sie sich das folgende SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

Es soll möglich sein, zu sehen, dass dies anfällig zu nutzen.
Stellen Sie sich vor dem id Parameter, um den gemeinsamen Angriffsvektor enthalten:

1 OR 1=1

Es gibt keine riskanten Zeichen in es zu kodieren, so dass es gerade durch den austretende Filter passieren. Verlassen Sie uns:

SELECT fields FROM table WHERE id= 1 OR 1=1

Welche ist eine schöne Injektion Vektor SQL und ermöglicht es dem Angreifer alle Zeilen zurück. Oder

1 or is_admin=1 order by id limit 1

, welche erzeugt

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

Welche der Angreifer erlaubt, den erste Administrator der Details in diesem völlig fiktiven Beispiel zurückzukehren.

Während diese Funktionen nützlich sind, müssen sie mit Vorsicht verwendet werden. Sie müssen sicherstellen, dass alle Web-Eingänge bis zu einem gewissen Grad überprüft werden. In diesem Fall sehen wir, dass wir ausgenutzt werden können, weil wir nicht überprüfen, ob eine Variable, die wir als Zahl verwendet haben, war tatsächlich numerisch. In PHP sollten Sie weit eine Reihe von Funktionen verwenden, um zu überprüfen, dass Eingänge ganze Zahlen sind, Schwimmern, alphanumerische usw. Aber wenn es um SQL kommt, die meisten den Wert der vorbereiteten Anweisung beachten. Der obige Code wäre sicher gewesen, wenn es sich um eine vorbereitete Erklärung, wie die Datenbankfunktionen war hätte gewusst, dass 1 OR 1=1 keine gültige wörtlichen ist.

Wie bei htmlspecialchars(). Das ist ein Minenfeld von selbst.

Es ist ein echtes Problem in PHP, dass es hat eine ganze Auswahl verschiedener HTML-bezogener entweichende Funktionen und keine klare Orientierung auf genau, welche Funktionen, was zu tun.

Erstens, wenn Sie in einem HTML-Tag, sind Sie in echten Schwierigkeiten. Schauen Sie sich

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

Wir sind schon in einem HTML-Tag, so dass wir nicht brauchen, etwas gefährlich zu tun. Unser Angriffsvektor nur javascript:alert(document.cookie) werden könnte

Jetzt resultierende HTML sieht aus wie

<img src= "javascript:alert(document.cookie)" />

Der Angriff wird gerade durch.

Es wird noch schlimmer. Warum? weil htmlspecialchars (wenn diese Art und Weise genannt) kodiert nur doppelte Anführungszeichen und nicht einzeln. Also, wenn wir hatten

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

Unser bösen Angreifer kann nun ganz neue Parameter injizieren

pic.png' onclick='location.href=xxx' onmouseover='...

gibt uns

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

In diesen Fällen gibt es keine magische Kugel, man muss nur die Eingabe selbst santise. Wenn Sie versuchen, und schlechte Zeichen herauszufiltern werden Sie sicherlich scheitern. Nehmen Sie einen Whitelist-Ansatz und nur durch die Zeichen lassen, die gut sind. Schauen Sie sich die XSS Blatt Beispiele auf betrügen, wie vielfältig Vektoren sein können

Auch wenn Sie htmlspecialchars($string) außerhalb von HTML-Tags verwenden, Sie sind immer noch anfällig für Multi-Byte-charset Angriffsvektoren.

Die effektivste Sie sein können, ist die eine Kombination aus mb_convert_encoding und htmlentities wie folgt zu verwenden.

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

Auch läßt diese IE6 verletzlich, wegen der Art, es UTF behandelt. Sie können jedoch auf eine begrenztere Codierung zurückgreifen, wie ISO-8859-1, bis IE6 Nutzung abfällt.

Für eine tiefergehende Untersuchung der multibyte Probleme finden Sie unter https://stackoverflow.com/a/12118602/1820

Andere Tipps

Neben Cheekysoft der ausgezeichneten Antwort:

  • Ja, sie werden Sie sicher halten, aber nur, wenn sie absolut richtig gewohnt sind. Verwenden Sie sie nicht richtig, und Sie werden immer noch anfällig sein, und kann andere Probleme (zum Beispiel Datenkorruption)
  • Bitte verwenden Sie Abfragen parametrisiert statt (wie oben angegeben). Sie können sie durch zum Beispiel verwenden PDO oder über einen Wrapper wie PEAR DB
  • Stellen Sie sicher, dass magic_quotes_gpc und magic_quotes_runtime sind jederzeit ab und geht nie aus Versehen eingeschaltet, nicht einmal kurz. Es handelt sich um einen früher und tief fehlgeleiteter Versuch von PHP-Entwicklern Sicherheitsprobleme zu verhindern (was zerstört Daten)

Es ist nicht wirklich ein Allheilmittel zur Vermeidung von HTML-Injektion (z Cross-Site-Scripting), aber Sie können in der Lage sein, es zu erreichen, leichter, wenn Sie eine Bibliothek oder Template-System verwenden zur Ausgabe von HTML. Lesen Sie die Dokumentation für den für, wie die Dinge in geeigneter Weise zu entkommen.

In HTML müssen die Dinge entgangen werden unterschiedlich je nach Kontext. Dies gilt vor allem für Strings werden in Javascript gesetzt.

Ich würde auf jeden Fall mit den oben genannten Stellen zustimmen, aber ich habe eine kleine Sache in Antwort auf Cheekysoft Antwort hinzuzufügen, und zwar:

  

Wenn es um Datenbankabfragen kommt,   immer versuchen, und die Verwendung vorbereitet   parametrisierte Abfragen. Die mysqli und   PDO-Bibliotheken unterstützen diese. Das ist   unendlich sicherer als Entkommen mit   Funktionen wie   mysql_real_escape_string.

     

Ja, mysql_real_escape_string ist   effektiv nur eine Zeichenfolge zu entkommen   Funktion. Es ist kein Wundermittel.   Alles, was es tun wird, ist gefährlich zu entkommen   Zeichen, damit sie sein können   sicher in einem einzigen Abfrage-String zu verwenden.   Wenn Sie jedoch noch nicht sanieren Ihre   Eingänge vorher, dann werden Sie   anfällig für bestimmte Angriffsvektoren.

     

Stellen Sie sich das folgende SQL:

     

$ result = „SELECT Felder FROM Tabelle   WHERE id =   “.Mysql_real_escape_string ($ _ POST [ 'id']);

     

Es soll möglich sein, zu sehen, dass dies   verwundbar zu nutzen. Stellen Sie sich die ID   Parameter enthielten, den gemeinsamen Angriff   Vektor:

     

1 OR 1 = 1

     

Es gibt keine riskanten Zeichen in dort   kodieren, so dass es gerade passieren   durch das entweichende Filter. Verlassen   wir:

     

SELECT Felder FROM Tabelle WHERE id = 1   OR 1 = 1

I codiert eine schnelle kleine Funktion, die ich in meiner Datenbank-Klasse setzen, die alles wird Streifen aus, die eine Anzahl ist nicht. Es nutzt preg_replace, so gibt es ein wenig mehr optimierte Funktion prob, aber es funktioniert in einer Prise ...

function Numbers($input) {
  $input = preg_replace("/[^0-9]/","", $input);
  if($input == '') $input = 0;
  return $input;
}

Also statt mit

  

$ result = "SELECT Felder FROM Tabelle WHERE id =" .mysqlrealescapestring ( "1 OR 1 = 1");

Ich würde verwenden

  

$ result = "SELECT Felder FROM Tabelle WHERE id =" .numbers ( "1 OR 1 = 1");

, und es würde die Abfrage sicher ausführen

  

SELECT Felder FROM Tabelle WHERE id = 111

Sicher, das hörte es nur aus der richtigen Zeile angezeigt wird, aber ich denke nicht, daß das ist ein großes Problem für wen auch immer versucht, SQL in Ihre Website zu injizieren;)

Ein wichtiges Stück des Puzzles ist Kontexten. Jemand "1 OR 1 = 1" als die ID zu senden ist kein Problem, wenn Sie jedes Argument in Ihrer Abfrage zitieren:

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"

Was ergibt:

SELECT fields FROM table WHERE id='1 OR 1=1'

das ist ineffektiv. Da Sie die Zeichenfolge sind entkommen, bricht die Eingabe kann nicht aus dem String-Kontext. Ich habe dies 5.0.45 von MySQL bis Version getestet, und einen String-Kontextes unter Verwendung für eine Integer-Spalte keine Probleme verursachen.

$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id'];

Funktioniert gut, noch besser auf 64-Bit-Systemen. Hüten Sie sich vor Ihren Systemen Einschränkungen bei Adressierung große Zahl zwar, aber für Datenbank-IDs funktioniert dies sehr gut 99% der Zeit.

Sie sollten sein, eine einzelne Funktion / Methode für Ihre Werte als auch die Reinigung. Auch wenn diese Funktion ist nur ein Wrapper für mysql_real_escape_string (). Warum? Denn ein Tag, wenn ein auf Ihre bevorzugte Methode ausnutzen Daten der Reinigung gefunden wird nur aktualisiert werden muß, um es zu einem Ort, sondern eine systemweite finden und ersetzen.

Warum, warum, würden Sie nicht sind Anführungszeichen um Benutzereingaben in SQL-Anweisung? scheint ziemlich dumm nicht zu! einschließlich Anführungszeichen in SQL-Anweisung würden "1 oder 1 = 1" ein vergeblicher Versuch machen, nicht wahr?

so jetzt, werden Sie sagen, „was ist, wenn der Nutzer ein Angebot umfasst (oder doppelte Anführungszeichen) in den Eingang?“

gut, einfache Lösung dafür: nur Benutzer input'd Anführungszeichen entfernen. zB: input =~ s/'//g;. Jetzt, so scheint es mir jedenfalls, dass Benutzereingaben gesichert werden würden ...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top