2010-08-28 12 views

Antwort

8

Ich denke, dass Sie zwei Sicherheitsprobleme verwirren: SQL injection und cross-site scripting (XSS).

Eine Website ist anfällig für SQL-Injection, wenn falsch sanierte Benutzereingaben in einer SQL-Abfrage verwendet werden, die an die SQL-Datenbank gesendet wird.Dieser Code zum Beispiel führt eine SQL-Injection-Schwachstelle:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] . "')"); 

Dieses Problem ist einfach durch die Flucht der Benutzereingabe mit einer Funktion zu beheben wie mysql_real_escape_string:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) . "')"); 

, dass ist alles, was Sie tun müssen, , aber der schwierige Teil besteht darin, sich daran zu erinnern, dies für jede Benutzereingabe zu tun, die in einer SQL-Anweisung verwendet wird.

Eine Website ist anfällig für siteübergreifende Skripts, wenn Benutzereingaben in HTML verwendet werden, die an einen Client gesendet werden. Dieser Code, beispielsweise führt eine XSS Verwundbarkeit:

echo "<div class='postmessage'>" . $_POST['postmessage'] . "</div>"; 

A XSS Verwundbarkeit durch entweichende der Benutzereingabe mit einer Funktion wie htmlspecialchars fixiert ist:

echo "<div class='postmessage'>" . htmlspecialchars($_POST['postmessage']) . "</div>"; 

Auch dies ist leicht zu machen, aber leicht vergessen.

Normalerweise werden Benutzereingaben, die in einer Datenbank gespeichert werden, um HTML zu einem späteren Zeitpunkt zurückzusenden, unverändert gespeichert. Das heißt, nur mysql_real_escape_string wird verwendet. Sie können jedoch Benutzereingaben entkommen XSS zu verhindern, und dann die XSS-sichere Zeichenfolge entkommen zu SQL-Injection zu verhindern:

mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) . "')"); 

Der Vorteil ist, dass Sie sich nicht erinnern müssen Werte aus der Datenbank zu entkommen mit htmlspecialchars bevor Sie sie in HTML schreiben. Der Nachteil ist, dass einige Werte mit verschiedenen Funktionen maskiert werden müssen. Zum Beispiel würde ein Benutzername wahrscheinlich mit htmlspecialchars escaped sein, aber eine "postmessage" könnte BBcode, Markdown oder eine Teilmenge von HTML erlauben. Wenn Sie alle Eingaben maskiert haben, um XSS zu verhindern, müssen Sie Werte aus der Datenbank mit z. B. htmlspecialchars_decode auswerten.

Ein Problem besteht darin, dass das Unscaping der gesperrten Zeichenfolge nicht immer die ursprüngliche Zeichenfolge zurückgibt (unescape(escape($orig)) ist nicht unbedingt dasselbe wie $orig). Auch mit htmlspecialchars und htmlspecialchars_decode wird ein anderes Anführungszeichen dieses Problem verursachen. Ein anderes Beispiel ist, dass, wenn strip_tags verwendet wird, Informationen unwiederbringlich entfernt werden; Sie können die strip_tags nicht rückgängig machen. Daher verwenden viele Entwickler mysql_real_escape_string nur zum Speichern von Werten in der Datenbank und htmlspecialchars (oder was auch immer), um eine Zeichenfolge aus der Datenbank vorzubereiten, die in HTML verwendet werden soll.

+0

Wäre es nicht besser, vorbereitete Anweisungen zu verwenden, sauberer zu betrachten und möglicherweise einfacher zu arbeiten, sobald Sie den Dreh raus haben. –

+1

@ Xeross: Definitiv. Vorbereitete Anweisungen erleichtern das konsequente Verlassen von Benutzereingaben. Bei der Beantwortung von OPs Frage wollte ich jedoch sicherstellen, dass er die Gründe für die Verwendung von mysql_real_escape_string (oder einem DB-Escaping-Mechanismus) und htmlentities (oder einem XSS-Escaping-Mechanismus) versteht. –

21

mysql_real_escape_string() ist die einzige Methode, die Sie hier brauchen.
Sie sollten keine htmlentities() noch urlencode() vor dem Einfügen von Daten in Ihre Datenbank tun. Bei diesen Methoden handelt es sich normalerweise um Code beim Rendern der Ansicht, die Sie Ihren Benutzern anbieten.

Eine bessere Möglichkeit, SQL Injection zu vermeiden, ist die Verwendung von vorbereiteten Anweisungen.


Ressourcen:

zum gleichen Thema:

+0

+1 für vorbereitete Anweisungen. Sie können auch in den richtigen Situationen mit der Leistung helfen. –

+0

+1 für vorbereitete Anweisungen –

+0

<3 Vorbereitete Anweisungen :) –

1

Sie sollten auch sicherstellen, "rund um den Ort, wo Sie Ihren Code einfügen verwenden.

Zum Beispiel, wenn Sie

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']); 

mysql_real_escape_string tun würde nichts helfen. Weil $ _POST ['userid'] nicht von 'umgeben ist.

So sollten Sie

$_POST['userid'] = mysql_real_escape_string($_POST['userid']); 
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\''); 

stattdessen tun.

Wenn Sie also mysql_real_escape_string für Ihre Variablen verwenden, heißt das nicht automatisch, dass sie in jeder Abfrage sicher sind.

Ein anderer Ansatz wäre, vorgefertigte Anweisungen zu verwenden.

1

Ja, aber es gibt einen Grund, mysql_real_escape_string() nicht zu verwenden. Zuerst ist es ein Schmerz zu tippen. Zweitens müssen Sie daran denken, es jedes Mal zu verwenden. Drittens macht es deinen Code hässlich. Viertens müssen Sie daran denken, Ihre Strings zu zitieren. Fünftens ist es schwieriger, auf diese Weise Blobs in eine db einzufügen.

Lernen PDO wird Ihr Leben auf lange Sicht verbessern. Es ist schwieriger zu lernen als einfach mysql_real_escape_string() zu verwenden, aber die langfristigen Vorteile überwiegen die Unannehmlichkeit einer Lernkurve.

Verwandte Themen