SQL Injection vermeiden

ukulele

Datenbank-Guru
Beiträge
5.107
Ich verarbeite per SQL mehrere Felder aus einer Tabelle in meinem Query. Eines davon kann für den Nutzer mit individuellem Text gefüllt werden, alle anderen werden durch Dropdown Menüs vom CRM Client mit festen Werten befüllt.

Jetzt will ich natürlich verhindern das so Sachen wie ' DROP TABLE durch blöde Umstände tatsächlich ausgeführt werden (wenn auch in der Umgebung ziemlich unwarscheinlich). Wenn ich den ' als Zeichen im Vorfeld einfach mit replace ersetze, wäre es dann noch möglich aus "dem Text" auszubrechen und tatsächlich SQL Befehle zu schreiben?
 
Werbung:
Ich verarbeite per SQL mehrere Felder aus einer Tabelle in meinem Query. Eines davon kann für den Nutzer mit individuellem Text gefüllt werden, alle anderen werden durch Dropdown Menüs vom CRM Client mit festen Werten befüllt.

Jetzt will ich natürlich verhindern das so Sachen wie ' DROP TABLE durch blöde Umstände tatsächlich ausgeführt werden (wenn auch in der Umgebung ziemlich unwarscheinlich). Wenn ich den ' als Zeichen im Vorfeld einfach mit replace ersetze, wäre es dann noch möglich aus "dem Text" auszubrechen und tatsächlich SQL Befehle zu schreiben?


Wenn das ein text ist, dann halt quoten. In PHP gibt es da Funktionen. Wenn Du ganz sicher gehen willst: prepared Statements nutzen. Wenn Du völlig paranoid bist: stored Procs schreiben, Security Definer setzen, und dem Otto-Normal-User Schreibrechte auf der DB / Tabelle entziehen. Für PG könnt ich Dir das zeigen. Aber ich denke, prepared statements für Deine Lieblings-DB bekommst _DU_ hin ;-)
 
Ich hab mich mit dem Thema bisher gar nicht befasst da die Eingabe derzeit durch meinen CRM Client (Windows Software, kein PHP oder so) übernommen und abgesichert wird. Ich habe allerdings auch an keiner anderen Stelle Text der in SQL Code verwendet wird.

Ich wollte eigentlich die schmalste Lösung nach dem Motto: Findest du ein Böses Zeichen verwerfe einfach den ganzen Code. Da mir keine andere Möglichkeit bekannt ist aus Text auszubrechen dachte ich eigentlich muss es reichen den Anführungsstrich zu Filtern.
Code:
DECLARE    @test VARCHAR(255)
SET        @test = 'SELECT * FROM unt'
EXEC(@test)

--(17 Zeile(n) betroffen)

SET        @test = 'SELECT * ''FROM unt'
EXEC(@test)

--Meldung 105, Ebene 15, Status 1, Zeile 1
--Kein schließendes Anführungszeichen nach der Zeichenfolge 'FROM unt'.

SET        @test = 'SELECT * ''FROM unt'
SET        @test = replace(@test,'''','')
EXEC(@test)

--(17 Zeile(n) betroffen)
Würde ich damit nicht jegliche Möglichkeit unterbinden?
 
Ich wollte eigentlich die schmalste Lösung nach dem Motto: Findest du ein Böses Zeichen verwerfe einfach den ganzen Code. Da mir keine andere Möglichkeit bekannt ist aus Text auszubrechen dachte ich eigentlich muss es reichen den Anführungsstrich zu Filtern.

Würde ich damit nicht jegliche Möglichkeit unterbinden?

Halte ich für, sorry, bescheuert. Es gibt ja auch Eigennamen oder so, wo das Zeichen legal drin vorkommt.

Was spricht gegen prepared Statements?
 
Es gibt ja auch Eigennamen oder so, wo das Zeichen legal drin vorkommt.
Nein in diesem Fall nicht. Der Nutzer kann Regeln erstellen die z.B. sagen Spalte A >= 200 und anhand dieser Regeln wird ein SELECT zusammengeklatscht. Wenn ein Strich drin vorkäme bräuchte ich es gar nicht erst ausführen.
Was spricht gegen prepared Statements?
Habe ich bisher nie anwenden müssen und mich erlich gesagt noch nicht mit auseinander gesetzt.
 
Nein in diesem Fall nicht. Der Nutzer kann Regeln erstellen die z.B. sagen Spalte A >= 200 und anhand dieser Regeln wird ein SELECT zusammengeklatscht. Wenn ein Strich drin vorkäme bräuchte ich es gar nicht erst ausführen.

Habe ich bisher nie anwenden müssen und mich erlich gesagt noch nicht mit auseinander gesetzt.

Ja, und?

Code:
test=# create table foo(id serial primary key, value text);
NOTICE:  CREATE TABLE will create implicit sequence "foo_id_seq" for serial column "foo.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
CREATE TABLE
test=*# prepare insert_foo(text) as insert into foo (value) values ($1);
PREPARE
test=*# execute insert_foo('bla');
INSERT 0 1

Wo genau ist das Problem?
 
Werde ich morgen mal testen. Der Spaltenname müsste in meinem Fall allerdings auch ein Parameter sein.
Code:
prepare insert_foo(text) as insert into foo ($1) values ($2);

execute insert_foo('spalte','bla');
Das dürfte aber gehen oder?
 
Werde ich morgen mal testen. Der Spaltenname müsste in meinem Fall allerdings auch ein Parameter sein.
Code:
prepare insert_foo(text) as insert into foo ($1) values ($2);

execute insert_foo('spalte','bla');
Das dürfte aber gehen oder?


Prepared Statement heißt, daß beim prepare der Plan erstellt wird. Wenn da die Spalte nicht feststeht, wird das wohl ned gehen...
 
Werbung:
Hab ich befürchtet. Ich könnte jetzt mehrere Statements vorbereiten aber um das richtige zu wählen dazu muss ich mir aber mal noch Gedanken machen.
 
Zurück
Oben