Alternative zu mysql_real_escape_string ohne Verbindung zur Datenbank

89

Ich möchte eine Funktion haben, die sich wie mysql_real_escape_string verhält, ohne eine Verbindung zur Datenbank herzustellen, da ich manchmal Trockentests ohne DB-Verbindung durchführen muss. mysql_escape_string ist veraltet und daher unerwünscht. Einige meiner Ergebnisse:

http://www.gamedev.net/community/forums/topic.asp?topic_id=448909

http://w3schools.invisionzone.com/index.php?showtopic=20064

Viet
quelle
1
+1 Ich schreibe selbst eine MySQL-Klasse und verwende mysql_real_escape_string () für die Parameterbindung. Ich vermeide die Verwendung von mysqli, da nicht alle Hosting-Programme es unterstützen. Ich vermeide auch Bibliotheken mit mehreren Dateien und Klassen. Was ich brauche, ist nur eine ordentliche und saubere Einzelklasse. Danke dir!
Viet
+1 auch für mich. Mein Anwendungsfall ist eine SugarCRM-APi, bei der ich SQL-Fragmente über die API an die Remote-SugarCRM-Instanz senden muss. Das ist zwar böse, aber es ist das, womit ich arbeiten muss (klopfe ein paar SugarCRM-Entwicklerköpfe zusammen). Ich muss Zeichenfolgen in SQL in der Anwendung, die die API verwendet und die völlig unabhängig von der Datenbank hinter der SugarCRM-Instanz ist, maskieren.
Jason

Antworten:

75

Es ist unmöglich, eine Zeichenfolge ohne DB-Verbindung sicher zu umgehen. mysql_real_escape_string()und vorbereitete Anweisungen benötigen eine Verbindung zur Datenbank, damit sie mit dem entsprechenden Zeichensatz aus der Zeichenfolge entkommen können. Andernfalls sind SQL-Injection-Angriffe mit Mehrbyte-Zeichen weiterhin möglich.

Wenn Sie nur testen , können Sie auch verwenden mysql_escape_string(), es ist nicht 100% garantiert gegen SQL-Injection-Angriffe, aber es ist unmöglich, etwas Sichereres ohne eine DB-Verbindung zu erstellen.

zu viel php
quelle
1
+1 Danke für den Hinweis. Ich bin mir nicht sicher, wie ich mit Multi-Byte-Zeichen gegen SQL-Injection-Angriffe testen soll.
Viet
2
Ich habe einen alten Code zum Aktualisieren erhalten. Es wird mysql_escape_stringohne Verbindung verwendet (versucht immer noch herauszufinden, warum). Da diese Funktion veraltet ist, frage ich mich nur, wie ich sie ersetzen kann. Es erscheint sicherlich vernünftig, den "entsprechenden Zeichensatz" in jeder Funktion anzugeben, die ihn ersetzt, ohne eine Verbindung herzustellen.
JohnK
3
Unmöglich? Was erhält mysql_real_escape_string von der Datenbankverbindung, bei der es sich nicht um Konfigurationsdaten handelt, die von Hand an eine entsprechende Funktion übergeben werden könnten? Bearbeiten: Lesen Sie einfach weiter unten, es ruft eine Bibliotheksfunktion in MySQL auf, sodass einige Verarbeitungen außerhalb von PHP stattfinden. Es mag immer noch portabel sein, aber es auf dem neuesten Stand zu halten, wäre ein Projekt für sich.
Jason
2
Was ist, wenn der DB-Zeichensatz im Voraus bekannt ist?
Jchook
7
Ja, wenn Sie den Zeichensatz kennen, was verhindert das Entkommen ohne Verbindung?
Johan
65

Nun, nach der mysql_real_escape_string Funktionsreferenz Seite: „mysql_real_escape_string () ruft MySQLs Bibliotheksfunktion mysql_real_escape_string, das die folgenden Zeichen entkommt: \ x00, \ n \ r, \,‘, "und \ X1a"

In diesem Sinne sollte die im zweiten Link angegebene Funktion genau das tun, was Sie benötigen:

function mres($value)
{
    $search = array("\\",  "\x00", "\n",  "\r",  "'",  '"', "\x1a");
    $replace = array("\\\\","\\0","\\n", "\\r", "\'", '\"', "\\Z");

    return str_replace($search, $replace, $value);
}
Zombat
quelle
6
Vielen Dank. Ich würde etwas anderes vorschlagen: Funktion Escape ($ aQuery) {Rückgabe strtr ($ aQuery, Array ("\ x00" => '\ x00', "\ n" => '\ n', "\ r" => '\ r', '\\' => '\\\\', "'" => "\'", '"' => '\"', "\ x1a" => '\ x1a')) ;; }
Viet
1
Warum wird \ x1a durch \\\ x1a anstelle von \\ x1a ersetzt? Ist das ein Tippfehler?
Michael Z
16
-1 Das ist extrem gefährlich. Wenn die Datenbankverbindung einen Multibyte-Zeichensatz verwendet, können einfache byteweise Ersetzungen wie diese zu einer Beschädigung der Daten führen (einschließlich der Escape- / Anführungszeichen). Dies kann von einem böswilligen Angreifer absichtlich ausgenutzt werden, um beliebiges SQL einzufügen.
Eggyal
Wenn Sie die Zeichensätze falsch verstehen, kann dies gefährlich sein. Wenn bei Multibyte-Zeichensätzen MySQL verwendet wird, kann jemand einfach ein Byte eingeben, um das \\ aufzuheben. Multiebyte-Zeichensätze können oft alles als zweites Byte annehmen, einschließlich \\ für MySQL. Es wird nicht als eigenständiges \\, sondern als Teil des Multibyte-Zeichens angesehen. Ich habe keine Ahnung, was mit UTF8 passiert. Ich würde hoffen, dass mit [0xB0, '\\'] beim Auftreffen auf ein ungültiges Byte \\ nur dieses Byte stoppt und erneut beginnt, anstatt es zu verschlucken.
jgmjgm
1
Wenn ich weiß, dass der Zeichensatz utf8 ist, ist es sicher, dies zu verwenden mb_strpos()(und mb_substr()ein ähnliches Verhalten zu erzeugen substr_replace())?
SOFe
28

Im direkten Gegensatz zu meiner anderen Antwort ist diese folgende Funktion wahrscheinlich sicher, selbst bei Mehrbyte-Zeichen.

// replace any non-ascii character with its hex code.
function escape($value) {
    $return = '';
    for($i = 0; $i < strlen($value); ++$i) {
        $char = $value[$i];
        $ord = ord($char);
        if($char !== "'" && $char !== "\"" && $char !== '\\' && $ord >= 32 && $ord <= 126)
            $return .= $char;
        else
            $return .= '\\x' . dechex($ord);
    }
    return $return;
}

Ich hoffe, jemand, der besser informiert ist als ich, kann mir sagen, warum der obige Code nicht funktioniert ...

zu viel php
quelle
+1 Danke für den zusätzlichen Aufwand. Ich werde mehr über Multi-Byte-bezogene SQL-Injektionen erfahren.
Viet
Ich denke, es sollte $ return sein. = '\ X'. Dechex ($ ord); stattdessen
Viet
1
Im Allgemeinen bevorzuge ich die Verwendung von '\\' auch in Zeichenfolgen in einfachen Anführungszeichen, nur weil ein einzelnes '\' das nächste Zeichen beeinflussen kann, wenn Sie nicht vorsichtig sind. Ich bin wahrscheinlich nur wieder OCD.
zu viel PHP
1
Diese Funktion folgt nicht den MySQL-Escape-Regeln und führt zu einem Verlust der Datenintegrität. "MySQL erkennt die in Tabelle 9.1," Escape-Sequenzen für Sonderzeichen "gezeigten Escape-Sequenzen. Bei allen anderen Escape-Sequenzen wird der Backslash ignoriert. Das heißt, das Escape-Zeichen wird so interpretiert, als wäre es nicht maskiert. Beispiel:" \ x " ist nur "x". " - dev.mysql.com/doc/refman/5.6/en/…
Velcrow
2
Bedeutet \ xAA tatsächlich mehr als den Text "xAA" in einem MySQL-String-Literal? Die Dokumentation scheint zu sagen, dass \ x keine besondere Bedeutung hat, daher wird das \ ignoriert. dev.mysql.com/doc/refman/5.0/en/string-literals.html
Jason
6

Aus weiteren Untersuchungen habe ich herausgefunden:

http://dev.mysql.com/doc/refman/5.1/en/news-5-1-11.html

Sicherheitsupdate:

Bei der Multi-Byte-Codierungsverarbeitung wurde eine Sicherheitslücke bei der SQL-Injektion gefunden. Der Fehler befand sich auf dem Server und hat die mit der C-API-Funktion mysql_real_escape_string () maskierte Zeichenfolge falsch analysiert.

Diese Sicherheitsanfälligkeit wurde von Josh Berkus und Tom Lane im Rahmen der projektübergreifenden Sicherheitskooperation des OSDB-Konsortiums entdeckt und gemeldet. Weitere Informationen zur SQL-Injection finden Sie im folgenden Text.

Diskussion. Bei der Multi-Byte-Codierungsverarbeitung wurde eine Sicherheitslücke für die SQL-Injektion gefunden. Eine Sicherheitslücke bei der SQL-Injektion kann eine Situation enthalten, in der der Benutzer möglicherweise SQL-Anweisungen in die Daten einfügt, die der Server ausführen wird, wenn ein Benutzer Daten zum Einfügen in eine Datenbank bereitstellt. In Bezug auf diese Sicherheitsanfälligkeit ist es möglich, das Escapezeichen in einigen Multi-Byte-Zeichensätzen (z. B. SJIS, BIG5 und GBK) zu umgehen, wenn Zeichensatz-unbewusstes Escapezeichen verwendet wird (z. B. Addslashes () in PHP). Infolgedessen kann eine Funktion wie addslashes () SQL-Injection-Angriffe nicht verhindern. Es ist unmöglich, dies auf der Serverseite zu beheben. Die beste Lösung besteht darin, dass Anwendungen die Zeichensatz-fähige Escape-Funktion verwenden, die von einer Funktion wie mysql_real_escape_string () angeboten wird.

Es wurde jedoch ein Fehler festgestellt, wie der MySQL-Server die Ausgabe von mysql_real_escape_string () analysiert. Selbst wenn die Zeichensatz-fähige Funktion mysql_real_escape_string () verwendet wurde, war eine SQL-Injection möglich. Dieser Fehler wurde behoben.

Problemumgehungen. Wenn Sie MySQL nicht auf eine Version aktualisieren können, die die Fehlerbehebung beim Parsen von mysql_real_escape_string () enthält, aber MySQL 5.0.1 oder höher ausführen, können Sie den SQL-Modus NO_BACKSLASH_ESCAPES als Problemumgehung verwenden. (Dieser Modus wurde in MySQL 5.0.1 eingeführt.) NO_BACKSLASH_ESCAPES aktiviert einen SQL-Standardkompatibilitätsmodus, in dem Backslash nicht als Sonderzeichen betrachtet wird. Das Ergebnis ist, dass Abfragen fehlschlagen.

Geben Sie die folgende SQL-Anweisung ein, um diesen Modus für die aktuelle Verbindung festzulegen:

SET sql_mode='NO_BACKSLASH_ESCAPES';

Sie können den Modus auch global für alle Clients festlegen:

SET GLOBAL sql_mode='NO_BACKSLASH_ESCAPES';

Dieser SQL-Modus kann auch automatisch aktiviert werden, wenn der Server mit der Befehlszeilenoption --sql-mode = NO_BACKSLASH_ESCAPES oder durch Festlegen von sql-mode = NO_BACKSLASH_ESCAPES in der Serveroptionsdatei (z. B. my.cnf oder my.ini) gestartet wird , abhängig von Ihrem System). (Fehler # 8378, CVE-2006-2753)

Siehe auch Bug # 8303.

Viet
quelle
1
Dies wurde vor langer Zeit behoben.
Ihr
2
Achten Sie auch darauf, dass NO_BACKSLASH_ESCAPES andere Sicherheitslücken entstehen .
Eggyal
2
Behoben in 5.1.11 - Der Link wurde unterbrochen, hier ist das Archiv: web.archive.org/web/20120501203047/http://dev.mysql.com:80/doc/…
Bastion