安全
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}
テーブル名またはフィールド名にパラメータを使用できないため、最初のクエリは失敗します。
2番目のクエリは安全ではありませんが、これを行う唯一の方法です。
安全を確保するにはどうすればよいですか?
文字列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
を2つ持つことはできません 1つの(サブ)クエリに含まれる