• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Unklarheit zu mysql_real_escape_string

NetAktiv

Senior HTML'ler
Hallo,

Auszüge aus PHP: mysql_real_escape_string - Manual zeigen, dass man zum Aufruf der Methode mysql_real_escape_string eine DB-Verbindung aufgebaut haben muss und dass (sehr wenigen) Zeichen ein Backslash \ vorangestellt wird. Bei mir treten da zwei Fragen auf:

1) Man muss eine DB-Verbindung haben, um die Methode zu verwenden. Ich will aber erst das SQL erstellen und dann DB-Connect und Execute durchführen. Gibt es eine fertige Alternative zu mysql_real_escape_string, die ohne DB-Connect auskommt? Klar, ich kann selbst ein paar Replace machen.

2) Als Beispiel für Angriffe wird immer etwas in der Art angeführt dass der Benutzer statt xxx die Folge xxx; drop table yyy eingibt. Das Problem ist also, dass man durch das Semikolon einen weiteren Befehl nach einer Eingabe einbettet. Aber das Semikolon wird laut Beschreibung durch mysql_real_escape_string nicht ersetzt/geändert, was hilft es dann für diese Art der Angriffe.
 
Zu 2.

Mysql in Verbindung mit PHP unterstuetzt keine Multi-Queries. Also brauchst du dir darum keine Sorgen machen.

PHP: mysql_query - Manual

Bei der Mysqli Erweiterung wird das zwar unterstuetzt, aber auch nur, wenn du mult_query() verwendest.
 
Die Gefahr entsteht eben dadurch, dass Strings verlassen werden und Nutzereingaben so als SQL-Syntax interpretiert werden. Wie genau die Syntax dann aussieht (ob sie Semikolons enthält oder nicht), ist für die Angriffsstruktur weniger wichtig.

Ein klassisches Beispiel ist auch:

PHP:
<?php

function myhashfunc($input) {
    return $input;
}

$_POST['name']     = 'admin\' --';
$_POST['password'] = 'egal';

$query = "
    SELECT
            `id`
    FROM
            `user`
    WHERE
            `name` = '" . $_POST['name'] . "'
        AND
            `password_hash` = '" . myhashfunc($_POST['password']) . "'
    ";

var_dump($query);

Code:
string(153) " SELECT `id` FROM `user` WHERE `name` = 'admin' --' AND `password_hash` = 'egal' "

Loggt den Angreifer als User „admin“ ein. (-- leitet einen Kommentar ein und beendet somit die Query.)

Schön ist auch immer, ein OR 1 in eine DELETE-Query reinzuschummeln, wodurch die WHERE-Bedingung für alle Datensätze wahr wird.

Da gibt es böse Dinge.



Zu 1) Na ja, es sind im Endeffekt nicht mehr als einige String-Ersetzungen, das stimmt schon. Der Grund, dass das am Datenbank-Adapter hängt, ist der, dass korrektes Escaping von der konkreten Implementation und Version des Adapters abhängt und auch teilweise von Umgebungseinstellungen. Ein Escaping-Mechanismus, der für Version 1 der Datenbank korrekt ist, muss nicht zwingend für Version 2 korrekt sein. Gewichtiger ist aber vielleicht der Aspekt, dass Escaping auch von weiteren Einstellungen wie Charsets abhängen kann.

- Chris Shiflett ▪ addslashes() Versus mysql_real_escape_string()

Ein DB-Adapter ist ein konsistentes Interface und sollte auch als solches genutzt werden.

Wenn du postest, warum du die Queries schon vor der Verbindung fertigstellen möchtest, könnten wir versuchen, Alternativen zu finden.
 
Wenn du postest, warum du die Queries schon vor der Verbindung fertigstellen möchtest, könnten wir versuchen, Alternativen zu finden.
Ich habe einfach schon ein fertiges Modul erstellt, bei dem alles ohne direkte Benutzereingaben lief. Dieses Modul macht
- Connect - Execute - Check-Result - Display-Result - Disconnect
Übergeben wurde lediglich das SQL, egal ob nun Insert, Update oder Delete oder gar Drop Table bzw. Create Table. Nun wollte ich lediglich bei einem Update die Eingabe über ein Formular erlaube, dann Validierien und am Ende das validierte SQL an das existierende Modul übergeben. Und ich wollte es nicht umschreiben :-) um ihm eventuell die bereits beim Validate erstellte Session mitzugeben.

Nachteil dieser Methode ist halt, dass ich für jedes Execute einen DB-Connect/Disconnect mache, aber ich bin mir nicht sicher, inwieweit eine SQL-Session einen PHP-Neuaufruf überlebt, also ich habe nicht versucht, die DB-Session als PHP-Session Variable zu definieren und so nur einen Connect für die gesamte PHP Session zu haben. Da es sich eigentlich nur um Tests für mich handelt, war es auch nicht so wichtig :-), wollte es halt nur wissen.

Ich denke, wenn es kritisch wäre, dann würde ich Prepared Statements verwenden, aber in meiner Testumgebung wird halt die Eingabeform völlig dynamisch aus einem vorhergehenden SELECT erstellt. Ich muss lediglich den Keyname für den Update wissen (keyvalue kann nicht geändert werden). Bei den anderen Feldern prüfe ich, ob die Eingabedaten dem erforderlichen Datentyp entsprechen, dann baue ich das SQL Update zusammen mit Where keyname=keyvalue und übergeb das dem Modul oben.
 
Zuletzt bearbeitet:
Zurück
Oben