mysql_real_escape_string(), SQL Injections

hallo,

ich habe meine MySQL-Statements zur Vermeidung von Sicherheitslücken
einheitlich mit mysql_real_escape_string() gesichert:

$db->query(sprintf("
INSERT INTO person (id, name)
VALUES (%d, '%s')
",
$userid,
mysql_real_escape_string($username)
));

Nun kann es ja vorkommen, dass Strings nicht zwangsläufig in
Anführungszeichen angegeben werden, beispielsweise bei solchen
Konstrukten:

SELECT * FROM person
WHERE id IN (%s)

oder

SELECT * FROM person
WHERE flags | %s

Beispiel:

$db->query(sprintf("
SELECT * FROM person
WHERE id IN (%s)
",
mysql_real_escape_string($ids)
));

Sind solche Statements sicher oder gibt es da irgendwas zu beachten?
Schöne Grüße, Steffen
steffen horst [ Sa, 10 November 2007 16:19 ] [ ID #1867541 ]

Re: mysql_real_escape_string(), SQL Injections

steffen horst schrieb:

> hallo,
>
> ich habe meine MySQL-Statements zur Vermeidung von Sicherheitslücken
> einheitlich mit mysql_real_escape_string() gesichert:
>
> $db->query(sprintf("
> INSERT INTO person (id, name)
> VALUES (%d, '%s')
> ",
> $userid,
> mysql_real_escape_string($username)
> ));

Sehr lobenswert. Würde es doch nur jeder so machen...

Allerdings kann es sein, daß mysql_real_escape_string() hier gern eine
geöffnete Connection hätte. Ich kenne mich mit dem Klassenkram da nicht
so richtig aus - aber ich vermute, daß die von Dir benutzte Klasse auch
so eine Funktion hat. Die wäre dann zu verwenden.
($db->real_escape_string() oder so)


> Beispiel:
>
> $db->query(sprintf("
> SELECT * FROM person
> WHERE id IN (%s)
> ",
> mysql_real_escape_string($ids)
> ));
>
> Sind solche Statements sicher oder gibt es da irgendwas zu beachten?

Genau diese Beispiel verdeutlicht es: Das genügt so nicht. Immerhin
escapet mysql_real_escape_string() nur wenige Zeichen, darunter ", ',
das Null-Byte, ASCII 26 und natürlich \. (Kann sein, daß ich noch ein
oder zwei vergessen habe...)

Insbesondere nicht ) und das ,.

Daher müßtest Du hier händisch sicherstellen, daß es sich im eine
kommaseparierte Liste von numerischen IDs handelt... (oder besser: sie
selbst zusammenbauen)


Thomas
Thomas Rachel [ So, 11 November 2007 08:44 ] [ ID #1867998 ]

Re: mysql_real_escape_string(), SQL Injections

steffen horst schrieb:
> hallo,
>
> ich habe meine MySQL-Statements zur Vermeidung von Sicherheitslücken
> einheitlich mit mysql_real_escape_string() gesichert:
>
> $db->query(sprintf("
> INSERT INTO person (id, name)
> VALUES (%d, '%s')
> ",
> $userid,
> mysql_real_escape_string($username)
> ));
>
> Nun kann es ja vorkommen, dass Strings nicht zwangsläufig in

Ich muss gestehen ich kann dir nicht ganz folgen. Strings haben immer in =

Quotes zu stehen da sonst die meisten Parser das Kommando nicht
auswerten koennen da spaetestens beim Auftreten eines Whitespace ein
Problem auftritt.

Es gibt Datenbanken da wuerdest du einen Fehler bekommen wenn du eine
"1" versucht in ein Feld zuschreiben welcher vom Typ INT oder
dergleichen ist. MySQL ist an der Stelle gnaedig.

> Anführungszeichen angegeben werden, beispielsweise bei solchen
> Konstrukten:
>
> SELECT * FROM person
> WHERE id IN (%s)
>
> oder
>
> SELECT * FROM person
> WHERE flags | %s
>
> Beispiel:
>
> $db->query(sprintf("
> SELECT * FROM person
> WHERE id IN (%s)
> ",
> mysql_real_escape_string($ids)
> ));


Wenn es sich bei $ids um nummerische IDs handelt dann ist da mit dem
mysql_real_escape_string() i.O, aber man wuerde das "...WHERE id IN
(%d)..." schreiben. Also %d anstelle von %s. Ob man dann
mysql_real_escape_string dann weglassen kann muesste ueberlegt werden.
Ich schaetze mal ja.


Gruss
Joerg

--
TakeNet GmbH, Geschaeftsfuehrer Wolfgang Meier
97080 Wuerzburg Tel: +49 931 903-2243
Alfred-Nobel-Straße 20 Fax: +49 931 903-3025
HRB Wuerzburg 6940 http://www.takenet.de
Joerg Behrens [ So, 11 November 2007 21:02 ] [ ID #1867999 ]

Re: mysql_real_escape_string(), SQL Injections

>> ich habe meine MySQL-Statements zur Vermeidung von Sicherheitslücken
>> einheitlich mit mysql_real_escape_string() gesichert:
>>
>> $db->query(sprintf("
>> INSERT INTO person (id, name)
>> VALUES (%d, '%s')
>> ",
>> $userid,
>> mysql_real_escape_string($username)
>> ));
>>
>> Nun kann es ja vorkommen, dass Strings nicht zwangsläufig in

>Ich muss gestehen ich kann dir nicht ganz folgen. Strings haben immer in
>Quotes zu stehen da sonst die meisten Parser das Kommando nicht
>auswerten koennen da spaetestens beim Auftreten eines Whitespace ein
>Problem auftritt.

Du hast recht: In SQL-Anweisungen müssen Strings in Anführungszeichen
stehen. Es gibt jedoch in MySQL einige Typen, die keine direkte (vor
allem notationsgetreue) Entsprechung in PHP bzw. sprintf() haben. So
findet sich zum Beispiel für Mengen in SQL ([i1,i2,i3,in]) nichts
äquivalentes in PHP, so dass diese als String ausgedrückt werden
müssen, unabhängig davon, ob es sich bei den Werten um Integer-Werte
handelt. Auch bei Flags und dem BIT-Feld muss man vorsichtig sein,
dass nicht versehentlich Binärstrings in Dezimalzahlen umwandelt
werden.


>> $db->query(sprintf("
>> SELECT * FROM person
>> WHERE id IN (%s)
>> ",
>> mysql_real_escape_string($ids)
>> ));
>
>Wenn es sich bei $ids um nummerische IDs handelt dann ist da mit dem
>mysql_real_escape_string() i.O, aber man wuerde das "...WHERE id IN
>(%d)..." schreiben. Also %d anstelle von %s. Ob man dann
>mysql_real_escape_string dann weglassen kann muesste ueberlegt werden.
>Ich schaetze mal ja.

Nein, "WHERE id IN (%d)" wäre in diesem Fall identisch zu WHERE id =
%d, weil sprintf() Dir mit '%d' keine kommaseparierte Liste beschert.
[Mit %f würdest Du abhangig vom locale wenigstens zwei Werte bekommen
können :)]

Das mysql_real_escape_string() kann übrigens bei %d immer weggelassen
werden, denn %d liefert immer eine Dezimalzahl, im Zweifel eben 0.

schöne grüße, steffen
steffen bruentjen [ Mo, 12 November 2007 11:02 ] [ ID #1868662 ]
PHP » de.comp.lang.php.datenbanken » mysql_real_escape_string(), SQL Injections

Vorheriges Thema: Mehrere Verbindungen zu MySQL nicht möglich?
Nächstes Thema: Problem beim Formatieren mit DATE_FORMAT und timestamp