Oracle
 sql >> Base de données >  >> RDS >> Oracle

Delphi - empêcher l'injection SQL

Sûr

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

Ce code est sûr car vous utilisez des paramètres.
Les paramètres sont toujours à l'abri de l'injection SQL.

Non sécurisé

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

N'est pas sûr car le nom d'utilisateur peut être name; Drop table_name; Entraînant l'exécution de la requête suivante.

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

Également dangereux

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

Parce que si le nom d'utilisateur est ' or (1=1); Drop Table_name; -- Il en résultera la requête suivante :

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

Mais ce code est sûr

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

Parce que IntToStr() n'acceptera que des entiers afin qu'aucun code SQL ne puisse être injecté dans la chaîne de requête de cette façon, uniquement des nombres (ce qui est exactement ce que vous voulez et donc autorisé)

Mais je veux faire des choses qui ne peuvent pas être faites avec des paramètres

Les paramètres ne peuvent être utilisés que pour les valeurs. Ils ne peuvent pas remplacer les noms de champs ou les noms de tables. Donc, si vous souhaitez exécuter cette requête

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

La première requête échoue car vous ne pouvez pas utiliser de paramètres pour les noms de table ou de champ.
La deuxième requête n'est pas sûre, mais c'est la seule façon d'y parvenir.
Comment rester en sécurité ?

Vous devez vérifier la chaîne tablename contre une liste de noms approuvés.

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

C'est la seule façon de faire cela, que je connaisse.

BTW Votre code d'origine contient une erreur :

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

Devrait être

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

Vous ne pouvez pas avoir deux where est dans une (sous-)requête