SQL Injection: Suche Infos

te one

Lt. Commander
Registriert
Apr. 2009
Beiträge
1.252
Hallo,

da ich unter Anderem hin und wieder auch Web-Anwendungen schreibe wollte ich mir heute mal das Thema "SQL Injection" ganz genau ansehen. Das es auf einfach Seiten funktioniert ist logisch. Hierfür habe ich eigens ein paar Seiten gebaut, in welche ich dann Code eingeschleust habe.
Nun sind aber zwei Fragen aufgekommen: (Zur Info: Ich arbeit mit XAMPP)

1. Selbst wenn der Datenbankuser sagen wir DELETE-Recht hat und er seinen Code hinten an ein SELECT-Statement anhängt,wird dies von mysql_query (PHP) anscheinend nicht ausgeführt.
Code:
SELECT * FROM test WHERE id=[B][U]1 or 3=3; DELETE FROM test[/U][/B]
Das unterstrichene ist Userinput. Hiervon scheint keine Gefahr auszugehen, da diese Art von Statements wohl beim connect erst aktiviert werden müsste (wenn ich das dem Handbuch richtig entnommen habe).

2. gibt es ja noch die schöne funktion mysql_real_escape_string()
Bei INT-Feldern funktioniert wie oben sichtbar eine Injection immer noch recht einfach (zumindest das select. Delete geht eben nicht). Doch lässt sich mysql_real_escape_string() nicht auch irgendwie umgehen bzw. durch eingebaute kommentare etc. aushebeln (hierzu habe ich mal einen trick mit der zeichenkodierung gefunden, wodurch man sich glaube ich die slashes in die query bauen konnte).
Wäre super wenn hier jemand ein bisschen Literatur weiß und die mir nennen kann. Ist ein echt interessantes Thema, da man als Entwickler zwar selbst ein paar Schwachstellen kennt, aber man doch manchmal im Bezug auf die Sicherheit ein recht mulmiges Gefühl hat.

Schonmal Danke und Gruß
 
PDO und Prepared Statements nutzen, und das SQL-Injection-Problem ist ein für alle mal gegessen.
 
@Luxuspur: Vielen Dank für diese hilfreiche Antwort. Wäre ich von selbst wohl nicht darauf gekommen. Die bisherige Literatur, die ich über Google gefunden habe (waren jetzt 5 Artikel hierzu) war schon sehr interessant, jedoch darauf ausgelegt, dass man gegen SQL-Injection wirklich garnichts unternommen hat. Dann lässt sich natürlich alles einschleußen. Mich hätte es mehr interessiert welche Gefahren zB trotz mysql_real_escape_string() noch lauern.

@ice-breaker: Wurde in den Artikeln auch mehrmals empfohlen.

Falls noch jemand einen Artikel zu den tatsächlichen Möglichkeiten trotz escape_string hat, wäre es sehr nett ihn hier zu posten. Googlen und dann 20 Artikel lesen, die meine Fragen nicht wirklich klären kann ich auch selbst...
 
te one schrieb:
Das unterstrichene ist Userinput. Hiervon scheint keine Gefahr auszugehen, da diese Art von Statements wohl beim connect erst aktiviert werden müsste (wenn ich das dem Handbuch richtig entnommen habe).
Kannst du erklären, woher du diese Info hast? Wäre mir neu - auch wenn ich kein MySQL-Experte bin.
 
Seine Infos sind nicht ganz korrekt. die PHP-Extension ext/mysql für die mysql_*-Funktionen unterstützt einfach aus Sicherheitsgründe keine mehrfachen SQL-Queries pro Funktionsaufruf, man dachte damals, dass man damit die SQL-Injektion-Problematik schon etwas abschwächen könnte.
 
Hab zu dem Thema noch etwas mehr gelesen.

Und zwar funktioniert es nicht zB ein DROP TABLE direkt nach einem SELECT auszuführen (wird von PHP unterbunden, außer man gibt es anfangs beim sql_connect() mit an).

Die einzigen Schwachstellen die anscheinend trotz ...escape_string() noch vorhanden sind ist bei bestimmten Zeichenkodierungen die Möglichkeiten (glaube das waren irgendwelche asiatischen oder so), dass man hier ein Hochkommata in den Code schleußen kann oder wenn man die escape-Funktion für zahlen nutzt oder weiteres zu prüfen.

In allen anderen Fällen scheint die escape-funktion von PHP komplett auszureichen. Bin jetzt eigentlich von mehr Schwachstellen ausgegangen... Aber eigentlich ein erfreuliches Ergebnis :)
 
Lass das, ganz einfach, das ist sau geführlich was du da machst.

Beispiel: Sei passwd(pw) eine Tabelle mit Passwörtern.
select * from test where 1=1 and 'a' in(select substr(pw,1) from passwd);

Jetzt kann jemand alle Zeichen anstelle von 'a' einsetzten und weiß damit den ersten Buchstaben eines Passwortes=>er kann mit linearer Laufzeit Passwörter herausfinden (und glaub mir, das ist mit einem Script in 1 Minute über das Internet erledigt).

Nehm also entweder mysql_real_escape_string oder einfach prepared statements. Ich empfehl dir prepared statements, auch wegen der Geschwindigkeit.
 
Natürlich mach ich das nicht ohne, nur weil man keine zwei verschiedenen statements gleichzeitig absetzen kann.
Aber ich wollte eben mal rausfinden, ob mysql_real_escape_string() ausreicht oder nicht. Und ich denke ich habe jetzt einen ganz guten einblick gewonnen.
Nämlich, dass es für textfelder gut funktioniert, man jedoch bei Zahlen aufpassen sollte. Oder man nutzt eben prepared statements.

Ist als soweit "gelöst".

Außer jemand kennt noch wege wie man mysql_real_escape_string() umgehen kann :)
 
Nein. Denn wenn du zahlen nicht auf zahlen prüfst, sondern nur mysql_rea_escape_string() nutzt, kann folgendes eingegeben werden:

...WHERE id=1 or 1=1....

Wobei die Benutzereingabe "1 or 1=1" war.
Bei Strings schützen dich in PHP die Anführungszeichen ;) WHERE id="var"
Somit hast du bei einer Stringübergabe vor und nach der variablen immer ein "
 
Hast du bei Zahlen im Zweifel auch. Ich setz grundsätzlich ein ' vor und hinter die Parameter.
 
SELECT * FROM table WHERE id = '1'; <- 1 is der GET-Parameter.
Da kannst du nix groß tun. Wenn du da "1 or 1=1" überträgst würde es innerhalb der 2 ' stehen. Es gibt aber keine ID für "1 or 1=1". In diesem Falle müsstest du "1' or 1=1' " übertragen, was aber vom real_escape_string abgefangen werden sollte.
 
Ähm nimmt der SQL-Server dann nicht eigentlich einen String entgegen und konvertiert diesen um? Denn eigentlich werden Zahlen in der Query ohne ' oder " angegeben...dachte ich...

denke richtig sql-konform ist das evtl nicht (aber man nagle mich nicht darauf fest)
 
Es funktioniert und es spart einem enorm viel Ärger, falls die Eingabe doch mal leer sein sollte. Während "...WHERE id = '';" korrekter Code ist, löst "...WHERE id =;" natürlich einen Fehler aus.
 
Ein Gegenstück zu mysql_real_escape_string() für Zahlenwerte gibt es nicht weil dazu die normalen Konvertierungsfunktionen reichen. Ich weiß grad nicht wie die bei PHP lauten, aber es gibt da garantiert etwas das einen String in einen Int (oder Double)-Zahlenwert wandelt. Diesen kannst du dann gefahrlos in den Query einbauen, ein reiner Zahlenwert kann keine SQL-Injection mehr auslösen.
 
Casting glaube ich in PHP per (int)$var
Naja mein Informationsdrang ist jetzt jedenfalls gestillt und ich bin wieder etwas schlauer geworden.
Fast schade für alle angreifer, dass man das thema sql-injection so einfach umschiffen kann.
 
Zahlen müssen sowieso auf Gültigkeit überprüft werden (wenn du ordentliche Software schreibst), dann muss die Eingabe sowieso zu einer gültigen Zahl konvertiert werden können. Z.B. Geburtsjahr -123: Das ist zwar eine gültige Zahl, aber kein gültiges Jahr.
 
Zurück
Oben