2016-10-25 2 views
2

Select Insert 문이 있는데 SQL injection에서 코드를 막아야하는지 궁금합니다. 이 코드는 BULK InsertTEMP TABLE을 사용합니다. 나는 전에 이것을 사용 해본 적이 없으며이 경우에 cfqueryparam을 사용할 수 있거나 사용해야한다면 익숙하지 않다. 그렇지 않으면 내가이 경우에 적용 할 수있는 다른 것이 있는가? 내가 INSERT/UPDATE 문을 cfloop를 사용하여 다중를 만들지 않도록 노력하기 때문에 대량를 사용하여 내 문제를 접근 한Insert 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> 

: 여기 내 코드입니다.

+0

스택 오버플로에서는 특정 항목이 "ok"인지 묻는 것이 좋지만 개방형 "개선"요청이 더 많은 경우 codereview.stackexchange.com이 더 적합합니다. 이를 염두에두고 질문에서 마지막 몇 문장을 제거했습니다. – Matt

+0

@Matt 당신이 위에 열거 한 두 사람에 대해 들어 보지 못했습니다. 알려 줘서 고마워. –

답변

1

아니요, 여기서는 cfqueryparam을 사용할 수 없습니다. 그러나 #cols#의 예외를 제외하고는 이러한 진술에 필요하지 않습니다.

CFQueryparam리터럴 (즉, 간단한 문자열, 날짜 등)이 sql 명령으로 실행되지 않도록 설계되었습니다. SELECT 문은 명령으로 해석 될 수있는 리터럴을 포함하지 않으므로 보호 할 필요가 없습니다.

위의 문구에서 발생할 수있는 한 가지 위험은 #cols# 변수입니다.이 변수는 열 이름 목록을 나타내는 것으로 보입니다. 개체 이름 (열 이름, 테이블 이름 등) 이 명령의 일부로 해석되어야합니다. cfqueryparam을 사용하면 그러한 일이 발생하지 않도록 설계되었습니다. 따라서 변수 #cols#을 보호하는 데 사용할 수 없습니다. 변수가 클라이언트 인 인 경우 직접 임의로 제거해야합니다.

데이터가 데이터베이스에 저장된 후에도 여전히 위험 할 수 있습니다. cfqueryparam을 사용하는 경우에도 악의적 인 값을 데이터베이스에 삽입 할 수 있습니다. CFQueryparam 마술처럼 입력 값을 안전하게 만들지 않습니다. 값 내의 악의적 인 명령이 실행되는 것을 막을뿐입니다 (현재 명령문에서만). INSERT 또는 UPDATE가 데이터베이스에 값을 저장하는 것을 중지하지 않으며 나중에 위험을 초래합니다. 동적 SQL의 어떤 종류를 사용하는 응용 프로그램의 경우, 저장된 값은 여전히 ​​second order SQL injection을 통해 위험을 초래할 수 있습니다 : 제출 된 값은 즉시 저장이 아닌 실행 악의적 인 명령을 포함 할 때

2 차 SQL 주입이 발생합니다. 경우에 따라 응용 프로그램에서 SQL 문 을 올바르게 인코딩하여 올바른 SQL로 저장할 수 있습니다. 그런 다음 해당 응용 프로그램의 다른 부분 인 에 SQL 인젝션을 방지하는 컨트롤이 없으면 저장된 SQL 문을 실행할 수 있습니다. 이 공격은

그래서 항상 CFQUERYPARAM를 사용하고, 바인드 변수를 사용하지 않는 동적 SQL을 피하기 위해 매우 중요합니다 .... 제출 값은 나중에 사용하는 방법에 대한 더 많은 지식을 필요로한다. 예를 들어 CF에서는 PreserveSingleQuotes을 사용하거나 SQL Server 저장 프로 시저에서 EXEC and use sp_executeSQL if needed을 사용하지 마십시오.

+0

제쳐두고, 데이터 스크러빙과 필터링 (즉, 트림 등)은 UPDATE가 아닌 임시 테이블에서 수행해야합니다. 짧고 달콤한 업데이트를 유지하십시오. – Leigh

+0

주사를 예방할 수있는 방법이 있습니까?마지막 단락은 내가 코드에서 누락 된 부분을 조금 혼란스럽게합니다. –

+1

업데이트 된 답변보기 요컨대, 항상 cfqueryparam 및 피하기 (매개 변수가없는) 동적 SQL. – Leigh

관련 문제