Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Delphi - verhindert SQL-Injection

Sicher

query.SQL.Text := 'select * from table_name where name=:Name';

Dieser Code ist sicher, weil Sie Parameter verwenden.
Parameter sind immer sicher vor SQL-Injection.

Unsicher

var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;

Ist unsicher, weil Benutzername name; Drop table_name; Dies führt dazu, dass die folgende Abfrage ausgeführt wird.

select * from table_name where name=name; Drop table_name;

Auch Unsicher

var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';

Denn wenn der Benutzername ' or (1=1); Drop Table_name; -- Das Ergebnis ist die folgende Abfrage:

select * from table_name where name='' or (1=1); Drop Table_name; -- '

Aber dieser Code ist sicher

var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);

Denn IntToStr() akzeptiert nur Ganzzahlen, daher kann auf diese Weise kein SQL-Code in die Abfragezeichenfolge eingefügt werden, sondern nur Zahlen (was genau das ist, was Sie wollen und daher erlaubt sind)

Aber ich möchte Sachen machen, die nicht mit Parametern gemacht werden können

Parameter können nur für Werte verwendet werden. Sie können keine Feldnamen oder Tabellennamen ersetzen. Wenn Sie also diese Abfrage ausführen möchten

query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName;      {works, but is unsafe}

Die erste Abfrage schlägt fehl, weil Sie keine Parameter für Tabellen- oder Feldnamen verwenden können.
Die zweite Abfrage ist unsicher, aber die einzige Möglichkeit, dies zu tun.
Wie bleiben Sie sicher?

Sie müssen den String tablename überprüfen gegen eine Liste genehmigter Namen.

Const
  ApprovedTables: array[0..1] of string = ('table1','table2');

procedure DoQuery(tablename: string);
var
  i: integer;
  Approved: boolean;
  query: string;
begin
  Approved:= false;
  for i:= lo(ApprovedTables) to hi(ApprovedTables) do begin
    Approved:= Approved or (lowercase(tablename) = ApprovedTables[i]);
  end; {for i}
  if not Approved then exit;
  query:= 'SELECT * FROM '+tablename;
  ...

Das ist die einzige Möglichkeit, dies zu tun, die ich kenne.

Übrigens Ihr ursprünglicher Code enthält einen Fehler:

query.SQL.Text := 'select * from table_name where name=:Name where id=:ID'; 

Sollte

sein
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID'; 

Sie können nicht zwei where haben 's in einer (Unter-)Abfrage