[PHP / MySQL] SQL-injection funktioniert nicht

Blutschlumpf

Fleet Admiral
Registriert
März 2001
Beiträge
20.521
Hi,

ich hab gerade ein Script gefunden welches Übergabewerte (die "1" im Code) direkt in eine SQL-Syntax übernimmt. Da man ja schon öfter von SQL-Injection gehört hat wollte ich testen ob das jemand ausgenutzt haben könnte.

Ich habe es hinbekommen, dass die SQL-Syntax vereinfach nachher etwa so aussieht:
Code:
SELECT * FROM xyz WHERE z = 1; DROP table abc;
Wenn ich das per phpmyadmin ausführe dropt der die Tabelle abc, wenn ich das als einen Befehlt per mysql_query übergebe, dann macht er nichts.

Gibts da irgendeine Einstellung die das bewusst verhindert oder warum klappt das nicht ?
PHP 4.3.10-16
Apache 1.3.33

Ich hab weiterhin probiert eine Subquery zu injecten die UPDATE, DROP oder DELETE aufruft, geht alles nicht, sobald in der Subquery was anderes als SELECT drin ist funktionierts nicht.

Wo ist also das Problem bzw. die Sicherheitslücke beim Injecten ?
 
Zuletzt bearbeitet:
kann es sein das es eine andere funktion dafür gibt?
also beim PDO-Objekt gibt es eine query() und eine exec() funktion...
kanns ja mal, ob du zu dem was findest...

greez krizi
 
mysql_exec oder ähnlich scheints nicht zu geben.

btw, mysql_error() sagt:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ';DROP TABLE abc' at line 1
Ich hab auch schon probiert die Einzelnen Statements oder Tabellennnamen zu quoten, hilft auch nichts.

Am DROP liegts auch nicht, DELETE funktioniert genausowenig mit 2 Befehlen. Einzeln funktionieren dann beide auch mit mysql_query().
 
Ok, danke für den Hinweis, beim Naheliegendsten (Anleitung zur Funktion) hab ich natürlich nicht nachgeguckt. (Scheiß Wald, ich seh die Bäume nicht ;))

mysql_query() sends an unique query (multiple queries are not supported) to the currently active database...
 
Normalerweise sieht das ca. so aus:

Statement:

execute("select userid from users where username='" + username + "' and password='" + password'")

Anmerkung: Das '" ist ein ' und ein " bzw. umgekehrt.

Wenn man es schlampig macht und username und password einfach so von der Maske einliest und nicht weiter bearbeitet, kann man folgendes erzeugen:

select userid from users where username='andr_gin'--' and password='test'

Auf der Maske gibt man folgendes ein:
Username: andr_gin'--
Password: test

Mit -- kann man den Rest der Zeile auskommentieren (es geht aber auch ohne Kommentar)
Dadurch kann man irgendein Passwort einsetzen, da nur der Username eine Rolle spielt.

Abfangen kann man das Ganze, indem man die ' durch zwei ' ersetzt. Dadurch kommt der User nicht dazu, dass er die Syntax des Statements verändern kann. Die '' werden dann beim Ausführen wieder durch ' ersetzt. Wenn jetzt z.B. der Username andr'gin wäre, dann würde es trotzdem funktionieren.
 
Ok, das klappt aber nur wenn du wirklich nen Login hast, nicht wenn irgendwo anders irgendwo ein Formular ungesichert ist oder im Falle oben.

Einer meiner Kollegen hats übrigens geschafft (natürlich auch nur mit Wissen der Datenbankstruktur) doch noch wa da raus zu holen.

Statt 2 Abfragen hintereinander zu machen verbindet man 2 Queries mit UNION und konnte in dem Fall Daten sammeln. Das funktioniert auch mit mysql_query().
 
Das mit dem Login war nur sein Beispiel. Man sollte grundsätzlich alle Strings in SQL ausbessern und aus ' ein '' machen. Damit sollte man aus Strings nicht mehr raus können und alles, was dann noch an Schwachsinn kommt, wird als Teil der Eingabe behandelt.
 
Hallo,

grundsätzlich hat andr_gin Recht. Besser jedoch wäre es von Anfang an, sofern es auf dem Server möglich ist, die PDO oder aber zumindest im Falle von MySQL, die mysqli Erweiterung und damit Prepared Statements zu nutzen. Diese bieten eine noch höhere Sicherheit gegenüber SQL-Injections, als das simple escapen von Strings. Zudem werden Prepared Statements in der Datenbank gecached, womit Sie beim 2. Ausführen schneller abgearbeitet werden. Im Falle der PDO ist man später sogar in der Lage, zumindest bei einfachen Queries das DBMS zu wechseln (z.B: Oracle oder Postgre) und am Quellcode quasi nichts verändern zu müssen, sofern man nicht das Feature der Buffered Queries von MySQL nutzt.


Ciao
 
Prepared Statements müssen aber auch von der Entwicklungsumgebung bzw. der Zugriffmethode unterstützt werden. In Java gibt es Prepared Statements, aber in VB.NET über ADO.NET sind mir z.B. noch keine untergekommen.
 
Zurück
Oben