저장 프로 시저 내에서이 쿼리에 대해 SQL 주입이 발생하지 않는 이유는 무엇입니까?


18

다음 저장 프로 시저를 만들었습니다.

ALTER PROCEDURE usp_actorBirthdays (@nameString nvarchar(100), @actorgender nvarchar(100))
AS
SELECT ActorDOB, ActorName FROM tblActor
WHERE ActorName LIKE '%' + @nameString + '%'
AND ActorGender = @actorgender

이제 이런 식으로 시도했습니다. 어쩌면 나는 이것을 잘못하고 있지만 그러한 절차가 SQL 주입을 막을 수 있기를 원합니다.

EXEC usp_actorBirthdays 'Tom', 'Male; DROP TABLE tblActor'

아래 이미지는 SSMS에서 위의 SQL이 실행되고 오류 대신 올바르게 표시되는 결과를 보여줍니다.

여기에 이미지 설명을 입력하십시오

Btw, 쿼리 실행이 완료된 후 세미콜론 뒤에 해당 부분을 추가했습니다. 그런 다음 다시 실행했지만 테이블 tblActor의 존재 여부를 확인했을 때 여전히 존재했습니다. 내가 뭔가 잘못하고 있습니까? 아니면 정말 주사 방지인가요? 나는 또한 여기에서 묻고 자하는 것이이 안전과 같은 저장 프로 시저라고 생각합니까? 감사합니다.


이것을 시도해 보셨습니까EXEC usp_actorBirthdays 'Tom', 'Male''; DROP TABLE tblActor'
MarmiK

답변:


38

이 코드는 다음과 같은 이유로 제대로 작동합니다.

  1. 매개 변수화 및
  2. 동적 SQL을 수행 하지 않음

SQL 인젝션이 작동하려면 쿼리 문자열을 작성하고 (하지 않는) 단일 아포스트로피 ( )를 이스케이프 된 아포스트로피 ( )로 변환 하지 않아야 합니다 (입력 매개 변수를 통해 이스케이프 된 것).'''

"손상된"값을 전달하려는 경우 'Male; DROP TABLE tblActor'문자열은 단순한 일반 문자열입니다.

이제, 당신이 다음 라인을 따라 무언가를하고 있다면 :

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'SELECT fields FROM table WHERE field23 = '
          + @InputParam;

EXEC(@SQL);

그런 다음 때문에 SQL 인젝션에 취약 것 쿼리는 현재, 사전 구문 분석 된 상황에서되지 않습니다; 해당 쿼리는 현재 다른 문자열입니다. 따라서 해당 쿼리는 다음과 같이 렌더링되고 실행되므로 문제 @InputParam가 될 수 있고 발생할 수 있습니다 '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;.

SELECT fields FROM table WHERE field23 = '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;

이것이 Stored Procedures를 사용하는 주요 이유 중 하나입니다. 본질적으로 더 안전합니다 (사용 된 매개 변수의 값을 확인하지 않고 위에서 보여준 것과 같이 쿼리를 작성하여 보안을 우회하지 않는 한). 동적 SQL을 빌드해야하는 경우 선호되는 방법은 다음을 사용하여 매개 변수화하는 것입니다 sp_executesql.

DECLARE @SQL NVARCHAR(MAX);

SET @SQL = N'SELECT fields FROM table WHERE field23 = @SomeDate_tmp';

EXEC sp_executesql
  @SQL,
  N'SomeDate_tmp DATETIME',
  @SomeDate_tmp = @InputParam;

시도 누군가에 전달하려면이 방법을 사용하여 '2015-10-31'; SELECT * FROM PlainTextCreditCardInfo;A의 DATETIME저장 프로 시저를 실행할 때 입력 매개 변수하면 오류를 얻을 것입니다. 또는 저장 프로 시저가 접수 되더라도 @InputParameterNVARCHAR(100), 그것은로 변환하는 것 DATETIME그에 통과하기 위해 sp_executesql호출. 그리고 동적 SQL의 매개 변수가 문자열 유형 인 경우에도 처음에 스토어드 프로 시저로 들어가면 단일 아포스트로피가 자동으로 이중 아포스트로피로 이스케이프됩니다.

공격자가 입력 필드를 아포스트로피로 채우려 고 시도하는 덜 알려진 유형의 공격이 있습니다. 예를 들어 저장 프로 시저 내부의 문자열이 동적 SQL을 구성하는 데 사용되지만 너무 작게 선언 된 문자열은 모든 것에 맞지 않을 수 있습니다 결말 아포스트로피를 밀어 내고 어떻게 든 문자열 내에서 더 이상 "탈출"되지 않도록 올바른 수의 아포스트로피로 끝납니다. 이를 SQL 잘림이라고하며 Bala Neerumalla의 "New SQL 잘림 공격 및 방지 방법"이라는 MSDN 잡지 기사에서 다루었지만 더 이상 온라인 기사는 아닙니다. MSDN Magazine 2006 년 11 월호이 기사가 포함 된 문제 는 Windows 도움말 파일로만 제공됩니다. .chm체재). 다운로드하면 기본 보안 설정으로 인해 열리지 않을 수 있습니다. 이 경우 MSDNMagazineNovember2006en-us.chm 파일 을 마우스 오른쪽 단추로 클릭 하고 "속성"을 선택하십시오. 이러한 탭 중 하나에는 "이 유형의 파일 신뢰"(또는 이와 유사한 것)에 대한 옵션이 있으며이를 확인 / 활성화해야합니다. "확인"버튼을 클릭 한 다음 .chm 파일을 다시 열어보십시오 .

잘림 공격의 또 다른 변형은 로컬 변수를 사용하여 이스케이프하기 위해 작은 따옴표를 두 배로 늘려서 "안전한"사용자 제공 값을 저장하는 데 사용되는 경우 해당 로컬 변수를 채우고 작은 따옴표를 배치하는 것입니다 끝에. 여기서 로컬 변수의 크기가 적절하지 않으면 두 번째 작은 따옴표의 끝에 충분한 공간이 없으며 변수를 작은 따옴표로 끝내고 작은 따옴표와 결합합니다 는 동적 SQL에서 리터럴 값을 종료하고 종료되는 작은 따옴표를 포함 된 이스케이프 된 작은 따옴표로 바꾸고 Dynamic SQL의 문자열 리터럴은 다음 문자열 리터럴을 시작하려는 다음 작은 따옴표로 끝납니다. 예를 들면 다음과 같습니다.

-- Parameters:
DECLARE @UserID      INT = 37,
        @NewPassword NVARCHAR(15) = N'Any Value ....''',
        @OldPassword NVARCHAR(15) = N';Injected SQL--';

-- Stored Proc:
DECLARE @SQL NVARCHAR(MAX),
        @NewPassword_fixed NVARCHAR(15) = REPLACE(@NewPassword, N'''', N''''''),
        @OldPassword_fixed NVARCHAR(15) = REPLACE(@OldPassword, N'''', N'''''');

SELECT @NewPassword AS [@NewPassword],
       REPLACE(@NewPassword, N'''', N'''''') AS [REPLACE output],
       @NewPassword_fixed AS [@NewPassword_fixed];
/*
@NewPassword          REPLACE output          @NewPassword_fixed
Any Value ....'       Any Value ....''        Any Value ....'
*/

SELECT @OldPassword AS [@OldPassword],
       REPLACE(@OldPassword, N'''', N'''''') AS [REPLACE output],
       @OldPassword_fixed AS [@OldPassword_fixed];
/*
@OldPassword          REPLACE output          @OldPassword_fixed
;Injected SQL--       ;Injected SQL--         ;Injected SQL--
*/

SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
           + @NewPassword_fixed + N''' WHERE [TableNameID] = '
           + CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
           + @OldPassword_fixed + N''';';

SELECT @SQL AS [Injected];

실행할 동적 SQL은 다음과 같습니다.

UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';

보다 읽기 쉬운 형식의 동일한 Dynamic SQL은 다음과 같습니다.

UPDATE dbo.TableName SET [Password] = N'Any Value ....'' WHERE [TableNameID] = 37 AND [Password] = N';

Injected SQL--';

이것을 고치는 것은 쉽다. 다음 중 하나를 수행하십시오.

  1. 절대적으로 필요한 경우를 제외하고 동적 SQL을 사용하지 마십시오 ! (나는 이것이 가장 먼저 고려해야하기 때문에 이것을 먼저 나열하고 있습니다).
  2. 전달 된 모든 문자가 작은 따옴표 인 경우를 위해 로컬 변수의 크기를 적절하게 조정하십시오 (즉, 입력 매개 변수 크기의 두 배 여야합니다).
  3. "고정 된"값을 저장하기 위해 로컬 변수를 사용하지 마십시오. REPLACE()동적 SQL을 작성 하는 데 직접 넣으십시오 .

    SET @SQL = N'UPDATE dbo.TableName SET [Password] = N'''
               + REPLACE(@NewPassword, N'''', N'''''') + N''' WHERE [TableNameID] = '
               + CONVERT(NVARCHAR(10), @UserID) + N' AND [Password] = N'''
               + REPLACE(@OldPassword, N'''', N'''''') + N''';';
    
    SELECT @SQL AS [No SQL Injection here];

    동적 SQL은 더 이상 손상되지 않습니다.

    UPDATE dbo.TableName SET [Password] = N'Any Value ....''' WHERE [TableNameID] = 37 AND [Password] = N';Injected SQL--';

위의 잘림 예제에 대한 참고 사항 :

  1. 예, 이것은 매우 고안된 예입니다. 15 자만 입력하면 할 수있는 일이 많지 않습니다. 물론 DELETE tableName파괴적 일 수 있지만 백도어 사용자를 추가하거나 관리자 암호를 변경할 가능성은 적습니다.
  2. 이 유형의 공격은 아마도 코드, 테이블 이름 등에 대한 지식이 필요할 것입니다 . 임의의 낯선 사람 / 스크립트 -kiddie에 의해 수행 될 가능성은 적지 만, 취약점을 알고있는 다소 화가 난 전직 직원에 의해 공격을받는 곳에서 일했습니다. 아무도 알지 못하는 특정 웹 페이지에서 즉, 공격자는 때때로 시스템에 대한 친밀한 지식을 가지고 있습니다.
  3. 물론, 모든 사람의 암호를 재설정 하는 것이 조사 될 가능성이 있으며, 이로 인해 공격이 발생했다는 사실을 회사에 알릴 수 있지만 여전히 백도어 사용자를 주입하거나 나중에 사용 / 탐색 할 보조 정보를 얻을 수있는 충분한 시간을 제공 할 수 있습니다.
  4. 이 시나리오가 대부분 학문적이지만 (실제 세계에서는 일어날 가능성이없는 경우에도) 여전히 불가능하지는 않습니다.

SQL 주입과 관련된 자세한 정보 (다양한 RDBMS 및 시나리오 포함)는 OWASP ( Open Web Application Security Project) 에서 다음을 참조하십시오.
SQL 주입 테스트

SQL 주입 및 SQL 잘림에 대한 관련 스택 오버플로 응답 :
'이스케이프 문자를 교체 한 후 T-SQL은 얼마나 안전합니까?


2
오, 정말 고마워요. 대단한 답변입니다. 지금은 이해. 공격자가 입력 필드를 아포스트로피로 채울 때 끝에 언급 한 기술도 실제로보고 싶습니다. 미리 감사드립니다. 나는 이것을 열지 않을 것입니다. 당신이 그것을 찾지 못하면 대답으로 선택하겠습니다.
라비

1
@ Ravi 링크를 찾았지만 더 이상 기사가 모두 보관되어 기사로 이동하지 않습니다. 그러나 몇 가지 정보와 유용한 링크를 추가했지만 여전히 해당 아카이브에서 기사를 찾으려고합니다.
Solomon Rutzky

1
srutzsky에게 감사합니다. OWASP 기사와 주입 테스트를 읽겠습니다. 보안 테스트를 위해 취약한 웹 앱인 'mutillidae'를 올바르게 기억하면 mutillidae에서 관리자로 웹 앱에 로그인하는 'OR 1 = 1'문자열을 사용하여 대학에서 SQL 주입을 수행했습니다. 생각한다. 그때 SQL 주입을 처음 소개했습니다.
Ravi

1
.chm 파일도 볼 수 없지만이 완벽한 답변과 stackoverflow의 링크 및 OWASP의 링크를 포함한 모든 유용한 링크에 감사드립니다. 나는 오늘 그것을 읽고 이것으로부터 많은 것을 배웠다.
Ravi

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.