Oracle
 sql >> база данни >  >> RDS >> Oracle

Delphi - предотвратяване на SQL инжектиране

Безопасно

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

Този код е безопасен, защото използвате параметри.
Параметрите винаги са безопасни от SQL инжекция.

Опасно

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

Не е безопасно, защото потребителското име може да бъде name; Drop table_name; В резултат на това се изпълнява следната заявка.

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

Също Опасно

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

Защото, ако потребителското име е ' or (1=1); Drop Table_name; -- Това ще доведе до следната заявка:

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

Но този код е безопасен

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

Тъй като IntToStr() ще приема само цели числа, така че по този начин в низа на заявката не може да бъде инжектиран SQL код, а само числа (което е точно това, което искате и следователно е разрешено)

Но искам да правя неща, които не могат да се правят с параметри

Параметрите могат да се използват само за стойности. Те не могат да заменят имена на полета или имена на таблици. Така че, ако искате да изпълните тази заявка

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

Първата заявка е неуспешна, защото не можете да използвате параметри за имена на таблици или полета.
Втората заявка не е безопасна, но е единственият начин, по който това може да се направи.
Как да останете в безопасност?

Трябва да проверите низа tablename срещу списък с одобрени имена.

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

Това е единственият начин за това, който знам.

BTW Вашият оригинален код има грешка:

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

Трябва да е

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

Не можете да имате две where е в една (под)заявка



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Получаване на грешка при използване на repeatStatement с интервал в заявката

  2. Как да посочите IN клауза в динамична заявка с помощта на променлива?

  3. Експортирайте резултатите от заявката на Oracle в HTML файл, когато използвате SQLcl

  4. Разделете голям текстов/CSV файл на множество файлове в PL SQL

  5. Преодоляване на ограничението за групови вмъквания през връзка към база данни