sql >> データベース >  >> RDS >> Oracle

Delphi-SQLインジェクションを防ぐ

    安全

    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つの(サブ)クエリに含まれる



    1. SubQueryMySQLを使用してINSERTINTO

    2. mysql recursive(tree)親子カテゴリ

    3. グループごとに2行のMYSQLGroupby Column

    4. LINQ-to-SQLは、データベースのデフォルト値が使用されるように、挿入時に指定されていない列を省略できますか?