mysql_real_escape_string(), SQL Injections

mysql_real_escape_string(), SQL Injections

am 10.11.2007 16:19:20 von steffen horst

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

Re: mysql_real_escape_string(), SQL Injections

am 11.11.2007 08:44:19 von Thomas Rachel

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

Re: mysql_real_escape_string(), SQL Injections

am 11.11.2007 21:02:04 von Joerg Behrens

steffen horst schrieb:
> hallo,
>=20
> ich habe meine MySQL-Statements zur Vermeidung von Sicherheitslücken
> einheitlich mit mysql_real_escape_string() gesichert:
>=20
> $db->query(sprintf("
> INSERT INTO person (id, name)
> VALUES (%d, '%s')
> ",
> $userid,
> mysql_real_escape_string($username)
> ));
>=20
> 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=20
auswerten koennen da spaetestens beim Auftreten eines Whitespace ein=20
Problem auftritt.

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

> Anführungszeichen angegeben werden, beispielsweise bei solchen
> Konstrukten:
>=20
> SELECT * FROM person
> WHERE id IN (%s)
>=20
> oder
>=20
> SELECT * FROM person
> WHERE flags | %s
>=20
> Beispiel:
>=20
> $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=20
mysql_real_escape_string() i.O, aber man wuerde das "...WHERE id IN=20
(%d)..." schreiben. Also %d anstelle von %s. Ob man dann=20
mysql_real_escape_string dann weglassen kann muesste ueberlegt werden.=20
Ich schaetze mal ja.


Gruss
Joerg

--=20
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

Re: mysql_real_escape_string(), SQL Injections

am 12.11.2007 11:02:59 von steffen bruentjen

>> 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