如何在Select Insert中阻止SQL注入?

时间:2016-10-25 14:57:05

标签: sql sql-server coldfusion bulkinsert

我有Select Insert语句,我想知道是否应该阻止我的代码从SQL注入。此代码使用BULK InsertTEMP TABLE。我以前从来没有使用过这个,如果在这种情况下我可以/应该使用cfqueryparam,或者在这种情况下我还能申请其他什么,我就不熟悉了?这是我的代码:

<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语句。

1 个答案:

答案 0 :(得分:1)

不,你不能在这里使用cfqueryparam。但是,除#cols#之外,您可能不需要这些语句。

CFQueryparam旨在防止 literals (即简单的字符串,日期等)作为sql命令执行。 SELECT语句不需要保护,因为它不包含任何可以解释为命令的文字。

上述语句中可能存在的一个风险是#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