Dennis: SQL Injections - escapen von Datenbank-/Tabellennamen

Beitrag lesen

Hi dedlfix,

Du bist fleißig gewesen - dein Posting ist schon total Self-Farben[1] ;-)

[1] …vor lauter Links :-)

Nein. Du hast übersehen, dass mysql_real_escape_string() sich neben dem " auch um den \ kümmert. Es kommt also foo \" bar raus.

Oh, stimmt, du hast Recht.

ist mysql_real_escape_string() auch dafür gedacht, auf Tabellennamen angewendet zu werden? Ich habe es bis jetzt immer mehr dafür gehalten, es auf quotierte Strings anzuwenden.

Es sieht mir auch so aus, als ob mysql_real_escape_string() nur für Werte und nicht für Identifier gedacht ist. Nach Lekture des Handbuchkapitels Database, Table, Index, Column, and Alias Names möchte ich meinen, dass es sogar ungeeignet ist. Dort steht auch, welche Zeichen nicht erlaubt sind und dass ein Backtick zu verdoppeln ist, wenn es Bestandteil eines in Backticks eingeschlossenen Bezeichners ist. Du müsstest also am Besten eine eigene Bezeichner-Quotier-Funktion/-Methode schreiben, die das alles berücksichtigt.

Gut, das entspräche ja schon mal dem, was ich mir gedacht habe - dass mysql_real_escape_string() hier nicht weiterhilft.

Doch denken wir mal konkret - ich zitiere noch mal einen Satz aus der von dir verlinkten Manual-Seite:
„If the character to be included within the identifier is the same as that used to quote the identifier itself, then you need to double the character.“

Das heißt, wir müssten im Tabellen- bzw. Datenbanknamen einfach nur alle ` durch `` ersetzen, damit wären sie entschärft. Ich behaupt jetzt auch mal noch, das man sonst kein weiteres Escaping betreiben muss, mal schauen:

Folgender SQL Code sei gegeben:
  SELECT * FROM $string

Für $string wird folgendes escaped (wie oben beschreiben) und danach eingesetzt:
  tabelle` WHERE foo = "bar"

Dabei käme herraus:
  SELECT * FROM tabelle`` WHERE foo="bar"

Dann sollte tabelle`` WHERE foo="bar" als Tabellennamen verwendet werden - das das keinen Slash, Backslash oder Punkt enthält, sollte das nach dem Manual ein gültiger Tabellenamen sein, allerdings wird die Tabelle nicht existieren ;-)

Bleib mal bei realistischen Beispielen! :-) Solche Mehrfachstatements werden von MySQL im Normalfall abgelehnt [...] Trotzdem bleibt die Möglichkeit, das eine erlaubte Statement so zu verändern, dass es ein anderes Ergebnis liefert als das vom Programmierer vorgesehene. Das reicht möglicherweise schon aus, um an Informationen zu kommen, die nicht für aller Leute Augen bestimmt waren.

Welche Möglichkeiten gäbe es noch? Ich habe oben jetzt noch eine WHERE Klausel angehängt, das wäre eigene Möglicheit, aber an mehr Informationen kommt man damit im Normalfall auch nicht, eher nur an weniger *g* Wobei mir gerade einfällt: Damit könnte es z.B. möglich sein, einen User-Account anzulegen (erneut), der bereits existiert und damit ein System rauszubringen - OK.

Doch was ließe sich noch machen, wenn wir uns auf ein SQL-Statement beschränken wollen? Eventuell noch so ORDER BY Geschichten und so, wäre natürlich böse, wenn das möglich wäre, aber ich wüsste nicht, wofür sich das ausnutzen ließe.

Dazu muss er aber voraussetzen, dass sie bis dahin noch nicht verwendet wurde. (Die Analyse des Konstruktor-Quelltexts, um das herauszufinden, ist keine sehr feine Option.)

Du meinst mit „sie“ die Klassenvariable? Von wem soll die benutzt worden sein? Gut, man muss sie natürlich setzen, bevor die Klasse selber sie verwendet.

MfG, Dennis.