Guten Abend!
Vielen Dank für die Tipps, die ich von Euch bekommen habe.
Ich komme mit dem Begriff SQL-Injection in dem von mir gefragten Beispiel nicht klar. Ich habe mir dazu ein youtube-Lernvideo angeschaut. In diesem Video hat ein Mensch in eine Suchanfrage heimlich in den Suchstring weitere SQL-Befehle eingebaut, die dann vom SQL-Server nicht als Suchanfrage gewertet wurden, sondern als Befehl interpretiert würde.
Auf das Beispiel von mir bezogen würde ich mir da vorstellen, dass z.B. in diese Zeile:
Code: Alles auswählen
records = [['1', '2', '3'], ['5', '6', '7'], ['9', '10', '11']]
heimlich etwas eingebaut wird, z.B.
Code: Alles auswählen
records = [['1', '2', '3'], ['5', '6', '7'], ['9', '10', '11 and where ID = 1']]
Viele Beispiele - die man auch im Netz findet, arbeiten dann aber auch mit dem %s in der execute-Anweisung für den SQL-Zugriff
Das ist jetzt einfach nur ein Beispiel, vielleicht funktioniert das mit "and whrere ID = 1" nicht, aber vom Prinzip her wird so einfach an irgendeiner Stelle der eigentliche SQL-Befehl abgeändert - so verstehe ich jetzt die SQL-Injection.
In dem youtube-Video konnte der Hacker über solche heimlichen Zusatzabfragen z.B. auf User-Tabellen drauf zugreifen und auch Passwörter ausspähen.
Aber ich kann doch Rechte definieren beim Erstellen der Benutzer. Wenn ich doch jetzt Benutzer erstelle, so kann ich doch genau definieren, welche SQL-Befehle ausgeführt werden dürfen und in welche Tabellen/Datenbanken der jeweilige User drauf zugreifen kann. Jetzt konnte z.B. der Gastuser auf die User-Tabelle mittels der Zusatzabfragen auch Werte aus dieser anderen Tabelle auslesen. Was ist aber denn, wenn ich diese Tabellen sperre?
Ich möchte ja in meinem Beispiel "nur" Werte in eine Datenbank schreiben. Also benötige ich den Befehl "INSERT INTO". Ich kann doch andere Befehle dem Benutzer entziehen, z.B. den drop-Befehl. Wenn also dann über den User heimlich ein drop-Befehl eingebaut wird, dann kann der doch garnicht ausgeführt werden. Genauso kann ich doch wichtige Tabellen, in der z.B. Passwörter gespeichert sind, sperren, die dann nur als root eingesehen werden können.
Aber die ganze SQL-Injection basiert doch darauf, dass jemand von Außen auf eine Datenbank drauf zugreift und z.B. über die Suchenfunktion heimlich seine Kommandos einbaut.
Das SQL-Kommando muss aber doch als String vorliegen, dementsprechend muss ich mir doch meine execute_command mit den Stringfeldern zusammenbauen.
Ihr schreibt mir jetzt in Euren Beiträgen, dass man keine Stringoperationen zum Zusammenbauen des SQL-Kommandos verwenden soll, und dass keine Platzhalter verwendet werden sollen:
Bei `execute()` sollte man weder den ``%`` noch die `format()`-Methode verwenden um Werte für eine Anfrage zu übergeben für die es Platzhalter gibt
In einem Eurer Beispielcodes steht doch auch der Befehl:
Wie soll ich denn ohne das "%s" einen Wert an das execute-Kommando senden, wenn der von einer Variablen kommt?
Ich bekomme von irgendwoher z.B. Messwerte. Diese Messwerte sollen z.B. die Werte sein, die hier stehen:
Code: Alles auswählen
records = [['1', '2', '3'], ['5', '6', '7'], ['9', '10', '11']]
Wie soll ich denn nun ohne ein &s oder das .format() die Werte in den Befehl einbauen? Ich stehe da grade echt vor einem Rätsel.
So wie ich Euch jetzt auch verstanden habe, besteht wo eine Gefahr darin, dass die Bezeichner beliebig sein sollen. Aber ich weis einfach nicht, wie ich das anders lösen soll. Ich benötige jetzt in meiner Tabelle vier Spalten. Es waren vorher erst drei Spalten, aber es ist ein Messwert hinzugekommen.
Ich kann natürlich den SQL-Befehl im Programm nicht variabel halten. Ändere ich nun die Anzahl der Parameter, dann kann ich im Quelltext etwas ändern. Ich wollte aber dazu übergehen, beim Programmstart die Informationen aus einer Initialisierungsdatei auszulesen. Genaus verhält es sich mit den Tabellen-Namen, die ich auf dem SQL-Server erstellt habe. Ich kann natürlich die Tabellennamen bei "INSERT INTO XXX (A, B, C)" einfach per Hand abändern "INSERT INTO XXX (Y, Z, V)". Aber von der späteren Administrierung des Programms ist es einfacher, wenn der SQL-Befehl variabel beim Programmstart angepasst werden kann.
Oder was ist, wenn ich in meinem Modul zum Senden an die Datenbank etwas einbaue und dieses Modul einmal für eine Tabelle mit 3 Messwerten verwende und an einer anderen Stelle von einem anderen Gerät mit zwei Messwerten? Ich könnte natürlich auch zweimal separate Funktionen für die eine Messerfassung haben und für die andere. Aber wenn ich dann später eine Anpassung vornehmen will/muss, die wäre dann an beiden Modulen vorzunehmen - was auch immer das sein könnte.
Im Summe fasse ich für mich jetzt zu der SQL-Injection-Problematik für mich zusammen - ich habe einen PC, an dem mehrere Geräte dranhängen, die Messwerte produzieren und in die Datenbank - die auf einem anderen Rechner liegt - abgespeichert werden. Es wird für den User, der dort schreiben darf, nur der "INSERT INTO" Befehl zugelassen. Andere Befehle dürfen dann doch garnicht ausgeführt werden können. Die Admin-Rechte auf dem MySQL-Server sind auf localhost beschränkt, jemand von einem anderen Rechner sollte also schon mal nicht ohne weiteres Admin-Rechte haben dürfen.
Eine andere Baustelle ist dann, was später mit den Messwerten weiter passiert. Dort könnte z.B. eine Webseite eine Datenbankabfrage durchführen - schicke mir alle Messwerte in Tabelle XYZ vom Datum X bis Datum Y. Dort könnte später z.B. ein Feld stehen, wo man die Werte eingeben kann. Aber um Werte abzufragen, benötige ich doch nur den Befehl "select". Und wenn das dann ein anderer User ist, als der von dem Rechner, welcher die Messwerte erfasst, und nur Werte auch nur aus dieser einen Tabelle lesen darf und keine anderen Abfragen möglich sind - spielt denn dann die SQL-Injection eine Rolle?
Für mich würde ich sagen, dass ich auf der Datenerfassungsseite, auf der ich mich gerade befinde, die Injection-Problematik nicht so stark beachten brauche. Vielleicht ist es auch ein Abwägen zw. einfacher Administrierung - wenn ich mir Spaltennamen etc. erst aus einer INI-Datei auslesen tue, dann aber den execute-Befehl mittels Stringoperationen erstellt werden muss - zu lasten der Sicherheit.