2016-10-25 9 views
2

Select Insertステートメントがあり、SQLインジェクションから自分のコードを防止する必要があるかどうかは疑問です。このコードはBULK InsertTEMP TABLEを使用しています。私はこの前にこれを使用したことがなく、この場合にはcfqueryparamを使用することができますか使用しなければならないのでしょうか?この場合、私が適用できる何か他のものがありますか?ここに私のコードは次のとおりです。Select InsertでSQLインジェクションを防ぐ方法は?

<cfquery datasource="testDB" name="InsertBulk"> 
    IF OBJECT_ID('tempdb..##TEMP_TBL') IS NOT NULL DROP TABLE ##TEMP_TBL; 

    CREATE TABLE ##TEMP_TBL (#cols#) 

    BULK INSERT ##TEMP_TBL 
    FROM 'D:\myFiles\myTXT.txt' 
    WITH (
     FIELDTERMINATOR = '\t', 
     ROWTERMINATOR = '\n' 
    ) 
</cfquery> 

<cfquery datasource="testDB" name="InsertUpdate"> 
    INSERT INTO myRecords(
     FIRST_NAME, 
     LAST_NAME, 
     GENDER,   
     DOB 
    ) 
    SELECT 
     CASE WHEN LEN(LTRIM(RTRIM(FIRST_NAME))) <> 0 OR FIRST_NAME <> 'NULL' THEN FIRST_NAME END, 
     CASE WHEN LEN(LTRIM(RTRIM(LAST_NAME))) <> 0 OR LAST_NAME <> 'NULL' THEN LAST_NAME END, 
     CASE WHEN LEN(LTRIM(RTRIM(GENDER))) <> 0 OR GENDER <> 'NULL' THEN GENDER END, 
     CASE WHEN LEN(LTRIM(RTRIM(BIRTH_DATE))) <> 0 OR BIRTH_DATE <> 'NULL' THEN BIRTH_DATE END 
    FROM ##TEMP_TBL AS TempInsert 
    WHERE NOT EXISTS (
     SELECT * 
     FROM myRecords AS Dups 
     WHERE Dups.userID = TempInsert.user_ID 
    ) 

    UPDATE Records 
    SET 
     Records.FIRST_NAME = CASE WHEN LEN(LTRIM(RTRIM(Temp.FIRST_NAME))) <> 0 OR Temp.FIRST_NAME <> 'NULL' THEN Temp.FIRST_NAME END, 
     Records.LAST_NAME = CASE WHEN LEN(LTRIM(RTRIM(Temp.LAST_NAME))) <> 0 OR Temp.LAST_NAME <> 'NULL' THEN Temp.LAST_NAME END, 
     Records.GENDER = CASE WHEN LEN(LTRIM(RTRIM(Temp.GENDER))) <> 0 OR Temp.GENDER <> 'NULL' THEN Temp.GENDER END, 
     Records.DOB = CASE WHEN LEN(LTRIM(RTRIM(Temp.BIRTH_DATE))) <> 0 OR Temp.BIRTH_DATE <> 'NULL' THEN Temp.BIRTH_DATE END, 
    FROM myRecords AS Records 
     INNER JOIN ##TEMP_TBL AS Temp 
      ON Records.userID = Temp.user_ID 
    WHERE Records.userID = Temp.user_ID 
</cfquery> 

私はcfloopを使用して、複数のINSERT/UPDATE文を作成しないようにしようとしたので、私はバルクを使用して私の問題にアプローチしてきました。

+0

Stack Overflowでは、特定のものが「ok」であることを確認することができますが、よりオープンな「改善」要求の場合は、codereview.stackexchange.comが適しています。これを念頭に置いて、あなたの質問から最後のいくつかの文章を削除しました。 – Matt

+0

@Matt私はあなたが上に挙げたそれらの2つについて聞いたことがありません。知らせてくれてありがとうございます。 –

答えて

1

いいえ、ここではcfqueryparamは使用できません。ただし、#cols#の例外を除き、これらのステートメントには必要ありません。

CFQueryparamは、リテラル(つまり、単純な文字列、日付など)がSQLコマンドとして実行されないように設計されています。 SELECTステートメントは、コマンドとして解釈できるリテラルを含んでいないため、保護する必要はありません。

上記の文で考えられる1つのリスクは、列名のリストを表すような#cols#変数です。オブジェクト名(列名、テーブル名など)は、コマンドの一部として解釈する必要があります。cfqueryparamを使用すると、それが起こらないように設計されています。したがって、変数#cols#を保護するためには使用できません。 変数がクライアントで提供されているの場合は、自分でスクラブを実行する必要があります。

データがデータベースに保存された後も、リスクはまだあります。 cfqueryparamを使用していても、悪意のある値をデータベースに挿入することはできます。 CFQueryparamは魔法のように入力値を安全にしません。これは、値内の悪意のあるコマンドが実行されないようにするだけです(現在のステートメントでのみ)。 INSERTまたはUPDATEによってデータベースに値が保存され、後でリスクが発生することはありません。動的SQLのいずれかの種類を使用するアプリケーションでは、格納された値は、まだsecond order SQL injectionを通じてリスクをもたらすことができます。

送信された値が格納されているのではなく、すぐに実行されている 悪質なコマンドが含まれている場合、二次SQLインジェクションが発生します。 場合によっては、アプリケーションが正しくSQLステートメント をエンコードし、有効なSQLとして格納することがあります。次に、そのアプリケーションの別の部分 は、SQLインジェクションから保護するコントロールがないと、その ストアドSQLステートメントを実行することがあります。この攻撃は 送信された値が後で使用されているかのより多くの知識を必要とする....

だから、常にでcfqueryparamを使用すると、バインド変数を使用しない、動的SQLを避けることが非常に重要です。たとえばCFでは、PreserveSingleQuotesを使用しないでください。またはSQL Serverのストアドプロシージャでは、EXEC and use sp_executeSQL if neededを使用しないでください。

+0

さて、データのスクラビングとフィルタリング(つまり、トリムなど)は、UPDATEではなくtempテーブルに対して行う必要があります。短いと甘い更新を維持します。 – Leigh

+0

注射を防ぐ方法はありますか?あなたの最後の段落は私のコードで私が見逃していることを少し混乱させます。 –

+1

更新された回答を参照してください。要するに、常にcfqueryparamと回避する(パラメータ化されていない)動的SQL。 – Leigh

関連する問題