Oracle
 sql >> Database >  >> RDS >> Oracle

Delphi:previene l'iniezione di SQL

Sicuro

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

Questo codice è sicuro perché stai usando parametri.
I parametri sono sempre al sicuro dall'iniezione SQL.

Non sicuro

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

Non è sicuro perché il nome utente potrebbe essere name; Drop table_name; Con conseguente esecuzione della query seguente.

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

Inoltre Non sicuro

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

Perché se il nome utente è ' or (1=1); Drop Table_name; -- Risulterà nella seguente query:

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

Ma questo codice è sicuro

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

Perché IntToStr() accetterà solo numeri interi, quindi nessun codice SQL può essere iniettato nella stringa di query in questo modo, solo numeri (che è esattamente quello che vuoi e quindi consentito)

Ma voglio fare cose che non possono essere fatte con i parametri

I parametri possono essere utilizzati solo per i valori. Non possono sostituire i nomi dei campi o delle tabelle. Quindi, se vuoi eseguire questa query

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

La prima query ha esito negativo perché non è possibile utilizzare i parametri per i nomi di tabelle o campi.
La seconda query non è sicura ma è l'unico modo in cui è possibile farlo.
Come mantenersi al sicuro?

Devi controllare la stringa tablename contro un elenco di nomi approvati.

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;
  ...

Questo è l'unico modo per farlo, che io sappia.

BTW Il tuo codice originale ha un errore:

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

Dovrebbe essere

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

Non puoi avere due where è in una (sotto)query