Seguro
query.SQL.Text := 'select * from table_name where name=:Name';
Este código é seguro porque você está usando parâmetros.
Os parâmetros estão sempre protegidos contra injeção de SQL.
Inseguro
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='+ UserName;
Não é seguro porque o nome de usuário pode ser
name; Drop table_name;
Resultando na execução da seguinte consulta. select * from table_name where name=name; Drop table_name;
Também Inseguro
var Username: string;
...
query.SQL.Text := 'select * from table_name where name='''+ UserName+'''';
Porque se username for
' or (1=1); Drop Table_name; --
Isso resultará na seguinte consulta:select * from table_name where name='' or (1=1); Drop Table_name; -- '
Mas este código é seguro
var id: integer;
...
query.SQL.Text := 'select * from table_name where id='+IntToStr(id);
Porque
IntToStr()
aceitará apenas números inteiros para que nenhum código SQL possa ser injetado na string de consulta dessa maneira, apenas números (que é exatamente o que você deseja e, portanto, permitido) Mas eu quero fazer coisas que não podem ser feitas com parâmetros
Os parâmetros só podem ser usados para valores. Eles não podem substituir nomes de campos ou nomes de tabelas. Portanto, se você deseja executar esta consulta
query:= 'SELECT * FROM :dynamic_table '; {doesn't work}
query:= 'SELECT * FROM '+tableName; {works, but is unsafe}
A primeira consulta falha porque você não pode usar parâmetros para nomes de tabelas ou campos.
A segunda consulta não é segura, mas é a única maneira de fazer isso.
Como você se mantém seguro?
Você tem que verificar a string
tablename
contra uma lista de nomes aprovados. 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;
...
Essa é a única maneira de fazer isso, que eu saiba.
BTW Seu código original tem um erro:
query.SQL.Text := 'select * from table_name where name=:Name where id=:ID';
Deveria estar
query.SQL.Text := 'select * from table_name where name=:Name and id=:ID';
Você não pode ter dois
where
está em uma (sub)consulta