sql >> Databasteknik >  >> RDS >> Oracle

Delphi - förhindra mot SQL-injektion

Säkert

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

Den här koden är säker eftersom du använder parametrar.
Parametrar är alltid säkra från SQL-injektion.

Osäkert

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

Är osäker eftersom användarnamn kan vara name; Drop table_name; Detta resulterar i att följande fråga exekveras.

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

Också Osäkert

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

Eftersom det är om användarnamn är ' or (1=1); Drop Table_name; -- Det kommer att resultera i följande fråga:

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

Men den här koden är säker

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

Eftersom IntToStr() accepterar bara heltal så ingen SQL-kod kan injiceras i frågesträngen på det här sättet, bara siffror (vilket är exakt vad du vill ha och därmed tillåtet)

Men jag vill göra saker som inte kan göras med parametrar

Parametrar kan endast användas för värden. De kan inte ersätta fältnamn eller tabellnamn. Så om du vill köra den här frågan

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

Den första frågan misslyckas eftersom du inte kan använda parametrar för tabell- eller fältnamn.
Den andra frågan är osäker men är det enda sättet detta kan göras på.
Hur håller du dig säker?

Du måste kontrollera strängen tablename mot en lista över godkända namn.

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

Det är det enda sättet att göra detta, som jag känner till.

BTW Din ursprungliga kod har ett fel:

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

Borde vara

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

Du kan inte ha två where är i en (under)fråga



  1. Radnummer per grupp i mysql

  2. Använder trigger för att se till att infogade data inte överskrider gränsen

  3. Använda SSH Tunneling som ett VPN-alternativ

  4. Spara data i mysql från hive hadoop till sqoop?