SQL Injection vermeiden

ukulele

Datenbank-Guru
Beiträge
4.702
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:

akretschmer

Datenbank-Guru
Beiträge
9.846
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 ;-)
 

ukulele

Datenbank-Guru
Beiträge
4.702
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?
 

akretschmer

Datenbank-Guru
Beiträge
9.846
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?
 

ukulele

Datenbank-Guru
Beiträge
4.702
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.
 

akretschmer

Datenbank-Guru
Beiträge
9.846
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?
 

ukulele

Datenbank-Guru
Beiträge
4.702
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?
 

akretschmer

Datenbank-Guru
Beiträge
9.846
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:

ukulele

Datenbank-Guru
Beiträge
4.702
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.
 
Oben