Ответ 1
Безопасный
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
в одном (под) запросе