Versuchen Sie bei Datenbankabfragen immer, vorbereitete parametrisierte Abfragen zu verwenden. Die mysqli
und PDO
Bibliotheken unterstützen dies. Dies ist unendlich sicherer als die Verwendung von Escape-Funktionen wie mysql_real_escape_string
.
Ja, mysql_real_escape_string
ist praktisch nur eine String-Escape-Funktion. Es ist kein Wundermittel. Alles, was es tun wird, ist, gefährliche Zeichen zu entkommen, damit sie sicher in einer einzelnen Abfragezeichenfolge verwendet werden können. Wenn Sie Ihre Eingaben jedoch nicht im Voraus bereinigen, sind Sie für bestimmte Angriffsmethoden anfällig.
Stellen Sie sich folgendes SQL vor:
$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);
Sie sollten sehen können, dass dies anfällig für Exploits ist.
Stellen Sie sich vor, der id
Parameter enthält den gemeinsamen Angriffsvektor:
1 OR 1=1
Es gibt keine riskanten Zeichen, die codiert werden müssen, sodass sie direkt durch den entweichenden Filter geleitet werden. Verlassen uns:
SELECT fields FROM table WHERE id= 1 OR 1=1
Dies ist ein schöner SQL-Injection-Vektor, der es dem Angreifer ermöglichen würde, alle Zeilen zurückzugeben. Oder
1 or is_admin=1 order by id limit 1
was produziert
SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1
Dadurch kann der Angreifer die Details des ersten Administrators in diesem vollständig fiktiven Beispiel zurückgeben.
Diese Funktionen sind zwar nützlich, müssen jedoch mit Vorsicht verwendet werden. Sie müssen sicherstellen, dass alle Web-Eingaben bis zu einem gewissen Grad validiert sind. In diesem Fall sehen wir, dass wir ausgenutzt werden können, weil wir nicht überprüft haben, ob eine Variable, die wir als Zahl verwendet haben, tatsächlich numerisch ist. In PHP sollten Sie häufig eine Reihe von Funktionen verwenden, um zu überprüfen, ob Eingaben Ganzzahlen, Gleitkommazahlen, alphanumerische Zeichen usw. sind. Beachten Sie jedoch bei SQL den Wert der vorbereiteten Anweisung am meisten. Der obige Code wäre sicher gewesen, wenn es sich um eine vorbereitete Anweisung handelte, da die Datenbankfunktionen gewusst hätten, dass 1 OR 1=1
es sich nicht um ein gültiges Literal handelt.
Wie für htmlspecialchars()
. Das ist ein eigenes Minenfeld.
Es gibt ein echtes Problem in PHP, dass es eine ganze Auswahl verschiedener HTML-bezogener Escape-Funktionen gibt und keine klare Anleitung, welche Funktionen genau was tun.
Erstens, wenn Sie sich in einem HTML-Tag befinden, sind Sie in echten Schwierigkeiten. Ansehen
echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';
Wir befinden uns bereits in einem HTML-Tag, sodass wir <oder> nichts Gefährliches tun müssen. Unser Angriffsvektor könnte einfach seinjavascript:alert(document.cookie)
Jetzt sieht das resultierende HTML so aus
<img src= "javascript:alert(document.cookie)" />
Der Angriff kommt direkt durch.
Es wird schlimmer. Warum? weil htmlspecialchars
(wenn es so genannt wird) nur doppelte Anführungszeichen und keine einfachen Anführungszeichen codiert. Also wenn wir hätten
echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";
Unser böser Angreifer kann jetzt ganz neue Parameter einfügen
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, Sie müssen nur die Eingabe selbst santisieren. Wenn Sie versuchen, schlechte Zeichen herauszufiltern, werden Sie sicherlich scheitern. Nehmen Sie einen Whitelist-Ansatz und lassen Sie nur die Zeichen durch, die gut sind. Schauen Sie sich das XSS-Spickzettel an, um Beispiele dafür zu finden, wie unterschiedlich Vektoren sein können
Selbst wenn Sie htmlspecialchars($string)
außerhalb von HTML-Tags verwenden, sind Sie dennoch anfällig für Multi-Byte-Zeichensatz-Angriffsvektoren.
Am effektivsten können Sie eine Kombination aus mb_convert_encoding und htmlentities wie folgt verwenden.
$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');
Selbst dies macht IE6 aufgrund der Art und Weise, wie es mit UTF umgeht, anfällig. Sie können jedoch auf eine eingeschränktere Codierung wie ISO-8859-1 zurückgreifen, bis die IE6-Nutzung abfällt.
Eine ausführlichere Studie zu den Multibyte-Problemen finden Sie unter https://stackoverflow.com/a/12118602/1820