sql >> Databáze >  >> RDS >> Oracle

Delphi - ochrana před SQL injection

Bezpečné

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

Tento kód je bezpečný, protože používáte parametry.
Parametry jsou vždy v bezpečí před vkládáním SQL.

Nebezpečné

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

Není bezpečné, protože Uživatelské jméno může být name; Drop table_name; Výsledkem je provedení následujícího dotazu.

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

Také Nebezpečné

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

Protože pokud je uživatelské jméno ' or (1=1); Drop Table_name; -- Výsledkem bude následující dotaz:

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

Tento kód je však bezpečný

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

Protože IntToStr() bude přijímat pouze celá čísla, takže tímto způsobem nelze do řetězce dotazu vložit žádný kód SQL, pouze čísla (což je přesně to, co chcete, a proto je povoleno)

Ale já chci dělat věci, které nelze dělat s parametry

Parametry lze použít pouze pro hodnoty. Nemohou nahradit názvy polí ani názvy tabulek. Pokud tedy chcete provést tento dotaz

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

První dotaz selže, protože nemůžete použít parametry pro názvy tabulek nebo polí.
Druhý dotaz není bezpečný, ale je to jediný způsob, jak to lze provést.
Jak zůstat v bezpečí?

Musíte zkontrolovat řetězec tablename proti seznamu schválených jmen.

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 je jediný způsob, jak to udělat, o kterém vím.

BTW Váš původní kód obsahuje chybu:

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

Mělo by být

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

Nemůžete mít dvě where 's v jednom (pod)dotazu



  1. Dotaz s nefunkčním dílčím výběrem by měl vést k chybě, ale vrátí řádky

  2. APACHE padá:Nadřazený:podřízený proces ukončen se stavem 3221225477 -- Restartování

  3. Laravel Migration Error:Chyba syntaxe nebo narušení přístupu:1071 Zadaný klíč byl příliš dlouhý; maximální délka klíče je 767 bajtů

  4. vypočítat hodiny na základě pracovní doby v Oracle SQL