Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Delphi - zapobiegaj wstrzykiwaniu SQL

Bezpieczny

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

Ten kod jest bezpieczny, ponieważ używasz parametrów.
Parametry są zawsze bezpieczne przed wstrzyknięciem SQL.

Niebezpieczne

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

Jest niebezpieczny, ponieważ nazwa użytkownika może być name; Drop table_name; Powoduje to wykonanie następującego zapytania.

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

Również Niebezpieczne

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

Ponieważ to, jeśli nazwa użytkownika to ' or (1=1); Drop Table_name; -- Spowoduje to następujące zapytanie:

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

Ale ten kod jest bezpieczny

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

Ponieważ IntToStr() przyjmie tylko liczby całkowite, więc żaden kod SQL nie może zostać w ten sposób wstrzyknięty do ciągu zapytania, tylko liczby (co jest dokładnie tym, czego chcesz, a zatem jest dozwolone)

Ale chcę robić rzeczy, których nie można zrobić za pomocą parametrów

Parametrów można używać tylko jako wartości. Nie mogą zastąpić nazw pól ani nazw tabel. Więc jeśli chcesz wykonać to zapytanie

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

Pierwsze zapytanie kończy się niepowodzeniem, ponieważ nie można użyć parametrów dla nazw tabel lub pól.
Drugie zapytanie jest niebezpieczne, ale jest to jedyny sposób, w jaki można to zrobić.
Jak zachować bezpieczeństwo?

Musisz sprawdzić ciąg tablename z listą zatwierdzonych nazwisk.

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

To jedyny sposób na zrobienie tego, jaki znam.

BTW Twój oryginalny kod zawiera błąd:

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

Powinien być

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

Nie możesz mieć dwóch where jest w jednym (pod)zapytaniu



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wyrenderować strukturę drzewa w stanie hibernacji z wieloma tabelami?

  2. TWÓRZ i UPUŚĆ PRZESTRZEŃ TABEL Oracle

  3. regexp_substr pomija puste pozycje

  4. jak napisać zapytanie sql, aby wybrać wiersze z maksymalną wartością w jednej kolumnie

  5. Użyj gv$session, aby sprawdzić, czy zapytanie się zawiesza