2016-10-25 3 views
2

Ich habe meine Select Insert-Anweisung und ich frage mich, ob ich meinen Code von SQL-Injektion verhindern sollte. Dieser Code verwendet BULK Insert und TEMP TABLE. Ich habe das vorher noch nie benutzt und mir ist nicht bekannt, ob ich in diesem Fall cfqueryparam verwenden kann oder sonst noch etwas, das ich in diesem Fall anwenden kann? Hier ist mein Code:Wie verhindert man die SQL-Injektion in Select Insert?

<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> 

Ich habe mein Problem mit Masse genähert, weil ich versuchte, INSERT/UPDATE-Anweisungen cfloop und Erstellen mehrere zu vermeiden.

+0

Fragen, ob eine bestimmte Sache "ok" ist, ist in Ordnung auf Stack Overflow, aber für mehr Open-End "Verbesserung" Anfragen ist codereview.stackexchange.com besser geeignet. In diesem Sinne habe ich die letzten Sätze aus Ihrer Frage entfernt. – Matt

+0

@Matt Ich habe noch nicht von den beiden oben genannten gehört. Danke für die Information. –

Antwort

1

Nein, Sie können cfqueryparam hier nicht verwenden. Mit der möglichen Ausnahme von #cols# benötigen Sie es jedoch nicht für diese Aussagen.

CFQueryparam wurde entwickelt, um zu verhindern, dass Literale (dh einfache Zeichenfolgen, Daten usw.) als SQL-Befehle ausgeführt werden. Die SELECT-Anweisung muss nicht geschützt werden, da sie keine Literale enthält, die als Befehle interpretiert werden könnten.

Das eine mögliche Risiko in den obigen Aussagen ist die #cols# Variable, die eine Liste von Spaltennamen darzustellen scheint. Objektnamen (Spaltennamen, Tabellennamen usw.) müssen als Teil eines Befehls interpretiert werden. Die Verwendung von cfqueryparam verhindert dies. Es kann also nicht zum Schutz der #cols# Variable verwendet werden. Wenn diese Variable vom Client bereitgestellt wird, müssen Sie selbst scrubben.

Bedenken Sie, dass auch nach dem Speichern von Daten in der Datenbank noch Risiken bestehen. Auch wenn Sie cfqueryparam verwenden, können weiterhin schädliche Werte in die Datenbank eingefügt werden. CFQueryparam macht einen Eingangswert nicht magisch sicher. Es verhindert lediglich, dass schädliche Befehle innerhalb des Wertes ausgeführt werden (und nur in der aktuellen Anweisung). Es verhindert nicht, dass ein INSERT oder UPDATE die Werte in der Datenbank speichert und später ein Risiko darstellt. Für Anwendungen können jede Art von dynamischem SQL gespeicherten Werte immer noch mit einem Risiko durch second order SQL injection Pose:

zweite Ordnung SQL-Injection tritt auf, wenn vorgelegte Werte bösartige Befehle enthalten, die sofort und nicht ausgeführt gespeichert sind. In einigen Fällen kann die Anwendung eine SQL-Anweisung korrekt codieren und sie als gültiges SQL speichern. Dann kann ein anderer Teil dieser Anwendung ohne Steuerelemente zum Schutz vor SQL-Injection die gespeicherte SQL-Anweisung ausführen. Dieser Angriff erfordert mehr Wissen, wie vorgelegten Werte später verwendet werden ....

So ist es sehr wichtig ist, immer cfqueryparam zu verwenden und dynamische SQL zu vermeiden, die nicht binden Variablen nicht verwendet. Vermeiden Sie beispielsweise in CF die Verwendung von PreserveSingleQuotes oder vermeiden Sie in gespeicherten SQL Server-Prozeduren EXEC and use sp_executeSQL if needed.

+0

Nebenbei sollten alle Daten schrubben und filtern (dh trimmen, usw.) an die temporäre Tabelle, nicht in der UPDATE getan werden. Halten Sie das UPDATE kurz und bündig. – Leigh

+0

Gibt es eine Möglichkeit, die Injektion zu verhindern?Dein letzter Absatz macht mich etwas verwirrt, was ich in meinem Code vermisse. –

+1

Siehe die aktualisierte Antwort. Kurz gesagt, immer cfqueryparam und vermeiden (nicht parametrisierte) dynamische sql. – Leigh