매개 변수가 실제로 Sql 주입을 방지하기에 충분합니까?


83

저는 동료들과 여기에서 SQL 쿼리, 특히 .NET 응용 프로그램에서 매개 변수를 사용하는 장점에 대해 설교했습니다. SQL 인젝션 공격에 대한 내성을 제공한다고 약속하기까지했습니다.

하지만 이것이 정말 사실인지 궁금해지기 시작했습니다. 매개 변수화 된 쿼리에 대해 성공할 알려진 SQL 주입 공격이 있습니까? 예를 들어 서버에서 버퍼 오버플로를 일으키는 문자열을 보낼 수 있습니까?

물론 웹 응용 프로그램이 안전한지 확인하기 위해 고려해야 할 다른 사항이 있습니다 (사용자 입력 및 모든 항목 삭제 등). 이제 SQL 주입을 생각하고 있습니다. 저는 MsSQL 2005 및 2008이 제 기본 데이터베이스이기 때문에 특히 관심이 있지만 모든 데이터베이스가 흥미 롭습니다.

편집 : 매개 변수 및 매개 변수화 된 쿼리가 의미하는 바를 명확히하기 위해. 매개 변수를 사용한다는 것은 문자열에 SQL 쿼리를 작성하는 대신 "변수"를 사용하는 것을 의미합니다.
따라서 이렇게하는 대신 :

SELECT * FROM Table WHERE Name = 'a name'

우리는 이것을합니다 :

SELECT * FROM Table WHERE Name = @Name

그런 다음 쿼리 / 명령 개체에서 @Name 매개 변수의 값을 설정합니다.


매개 변수가 의미하는 바를 명확히해야합니다 (Jonathan Leffler가 지적했듯이)-저장 프로 시저 매개 변수를 생각하고 있었지만,? parms 및 {0} parms ...
Steven A. Lowe

말하기가 훨씬 쉽습니다. 쿼리를 작성하는 데 연결을 사용하지 않습니다.

태그가 asp.net이므로 웹 애플리케이션을 빌드하고 있다고 가정합니다. 이 경우 XSS 공격 및 기타 공격도 처리해야합니다
Spikolynn

답변:


50

자리 표시 자는 주사를 예방하기에 충분합니다. 여전히 버퍼 오버플로에 대해 열려있을 수 있지만 이는 SQL 주입과는 완전히 다른 유형의 공격입니다 (공격 벡터는 SQL 구문이 아니라 바이너리입니다). 전달 된 매개 변수는 모두 적절하게 이스케이프되므로 공격자가 "실시간"SQL처럼 취급되는 데이터를 전달할 방법이 없습니다.

자리 표시 자 내에서 함수를 사용할 수 없으며 자리 표시자를 문자열 리터럴로 이스케이프 및 따옴표로 묶기 때문에 열 또는 테이블 이름으로 사용할 수 없습니다.

그러나 동적 쿼리 내 에서 문자열 연결의 일부로 매개 변수 를 사용하는 경우 문자열이 이스케이프되지 않고 리터럴이기 때문에 여전히 주입에 취약합니다. 매개 변수에 다른 유형 (예 : 정수)을 사용하는 것은 안전합니다.

즉, 입력을 사용하여와 같은 값을 설정하는 경우 security_level누군가가 시스템에서 스스로 관리자가되어 모두에게 자유로울 수 있습니다. 그러나 이것은 기본 입력 유효성 검사일 뿐이며 SQL 주입과는 관련이 없습니다.


요점은 @mikekidder가 인용 한 기사에서도 지적한 Steve Lowe의 답변에 의해 제기 된 문제를 이해하는 것입니다. 애플리케이션이든 서버이든 동적 SQL이 어디에 있든주의해야합니다. 동적 SQL은 위험하지만 안전하게 만들 수 있습니다.
Jonathan Leffler

"공격자가 '실시간'SQL처럼 취급되는 데이터를 전달할 수있는 방법은 없습니다." -이것은 사실이 아닙니다. 아래 예를 참조하십시오.
Booji Boy

아래의 모든 예는 매개 변수를 받아들이는 SQL 코드를 의미하는 "매개 변수화 된 쿼리"를 정의합니다. 일반 정의는 DBMS 매개 변수 컬렉션을 사용하는 쿼리입니다. DBMS 버그를 제외하고이 후자의 기술은 SQL 주입을 방지합니다.
HTTP 410

2
나는 모든 링크를 읽었습니다. DBMS 매개 변수 컬렉션에 대해 작동중인 주입 공격을 나타내는 링크를 인용하십시오. 실제로 귀하가 게시 한 링크는이 접근 방식을 SQL 주입 방지 ( "Type-Safe SQL 매개 변수 사용"섹션 참조)라고 특별히 언급합니다.
HTTP 410

안녕하세요! 그 대답을 증명하기 위해 Oracle SQL 문법 또는 이와 유사한 링크를 제공 할 수 있습니까? 나는 그것을 이해하고 당신과 절대적으로 동의하지만 문서, 문법 등에 대한 공식 링크가 있으면 좋을 것입니다. BestRegards, Raimbek
Raimbek Rakhimbek

13

아니요. 검증되지 않은 데이터를 SQL 쿼리에 삽입 할 때마다 SQL 주입의 위험이 있습니다.

쿼리 매개 변수는 SQL 구문에서 리터럴 값을 분리하여 이러한 위험을 방지하는 데 도움이됩니다.

'SELECT * FROM mytable WHERE colname = ?'

괜찮지 만 쿼리 매개 변수를 사용할 수없는 동적 SQL 쿼리에 데이터를 삽입하는 다른 목적이 있습니다. 이는 SQL 값이 아니라 테이블 이름, 열 이름, 표현식 또는 기타 구문이기 때문입니다.

'SELECT * FROM ' + @tablename + ' WHERE colname IN (' + @comma_list + ')'
' ORDER BY ' + @colname'

저장 프로 시저를 사용하는지 또는 애플리케이션 코드에서 직접 동적 SQL 쿼리를 실행하는지는 중요하지 않습니다. 위험은 여전히 ​​존재합니다.

이러한 경우의 해결책은 필요에 따라 FIEO 를 사용하는 것입니다 .

  • 필터 입력 : 데이터를 보간하기 전에 데이터가 합법적 인 정수, 테이블 이름, 열 이름 등과 같은지 확인합니다.

  • 이스케이프 출력 : 이 경우 "출력"은 데이터를 SQL 쿼리에 넣는 것을 의미합니다. 함수를 사용하여 SQL 표현식에서 문자열 리터럴로 사용되는 변수를 변환하여 문자열 내의 따옴표와 기타 특수 문자를 이스케이프합니다. 또한 함수를 사용하여 테이블 이름, 열 이름 등으로 사용되는 변수를 변환해야합니다. 전체 SQL 표현식을 동적으로 작성하는 것과 같은 다른 구문의 경우 더 복잡한 문제입니다.


12

"매개 변수화 된 쿼리"의 정의에 대해이 스레드에서 약간의 혼란이있는 것 같습니다.

  • 매개 변수를 허용하는 저장 프로 시저와 같은 SQL.
  • DBMS 매개 변수 컬렉션을 사용하여 호출되는 SQL입니다.

이전의 정의를 고려할 때 많은 링크가 작동하는 공격을 보여줍니다.

그러나 "정상적인"정의는 후자입니다. 그 정의를 감안할 때 작동 할 SQL 주입 공격에 대해 알지 못합니다. 그것은 하나가 없다는 것을 의미하지는 않지만 아직 보지 못했습니다.

의견에서 나는 내 자신을 충분히 명확하게 표현하고 있지 않으므로 여기에 더 명확해질 예가 있습니다.

이 접근 방식 SQL 주입에 개방되어 있습니다.

exec dbo.MyStoredProc 'DodgyText'

이 접근 방식 SQL 주입에 개방 되지 않습니다.

using (SqlCommand cmd = new SqlCommand("dbo.MyStoredProc", testConnection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    SqlParameter newParam = new SqlParameter(paramName, SqlDbType.Varchar);
    newParam.Value = "DodgyText";
    .....
    cmd.Parameters.Add(newParam);
    .....
    cmd.ExecuteNonQuery();
}

매개 변수를 허용하는 프로 시저와 반대로 DBMS 매개 변수 콜렉션이 의미하는 바를 명확히 할 수 있습니까?
Rune Grimstad

Rune,이 링크의 "Use Type-Safe SQL Parameters"섹션을 읽으십시오. msdn.microsoft.com/en-us/library/ms161953.aspx
HTTP 410

내 답변은 업데이트로 수정되기 전에 룬의 원래 질문에 대한 것이 었습니다.
mikekidder

SQL 주입에 대한 msdn-article을 읽고 다시 읽었지만 저장 프로 시저가 사용하는 매개 변수와 동적 쿼리가 사용하는 매개 변수 사이에 어떻게 다른지 알 수 없습니다. 동적 쿼리가 동적이라는 사실 외에도. 여전히 매개 변수를 바인딩해야합니다.
Rune Grimstad

차이를 만드는 것은 바인딩입니다. 매개 변수를 사용하여 저장된 proc을 직접 호출하면 입력 필터링이 수행되지 않습니다. 그러나 예를 들어 .NET에서 SqlCommand 매개 변수 컬렉션을 사용하여 바인딩하면 모든 매개 변수가 필터링되고 일반 텍스트로 처리됩니다.
HTTP 410

10

동적 쿼리를 구성하는 데 사용되는 문자열 유형 (varchar, nvarchar 등)의 모든 SQL 매개 변수는 여전히 취약합니다.

그렇지 않으면 매개 변수 유형 변환 (예 : int, decimal, date 등)은 매개 변수를 통해 SQL을 주입하려는 시도를 제거해야합니다.

편집 : @ p1 매개 변수가 테이블 이름이되는 예

create procedure dbo.uspBeAfraidBeVeryAfraid ( @p1 varchar(64) ) 
AS
    SET NOCOUNT ON
    declare @sql varchar(512)
    set @sql = 'select * from ' + @p1
    exec(@sql)
GO

드롭 다운 목록에서 @ p1을 선택하면 잠재적 인 sql-injection 공격 벡터입니다.

@ p1이 사용자가 개입 할 수있는 능력없이 프로그래밍 방식으로 공식화되면 잠재적 인 SQL 주입 공격 벡터가 아닙니다.


아니; 요점은 DBMS에 전달 된 문자열이 SQL 문의 일부가 아니라는 것입니다. 따라서 문자열의 값은 SQL에서 참조하는 값만 SQL 해석에 차이가 없습니다.
Jonathan Leffler

이것이 내가 매개 변수를 보는 방법이기도합니다. 그들은이 문제를 방지해야합니다.
Rune Grimstad

2
예를 들어 문자열을 사용하여 sp_executeSql (sql server)과 같은 것을 실행하는 sp에 문자열을 전달하는 경우 Steven이 옳습니다. 그러면 여전히 SQL 주입 위험이 있습니다.
alexmac

@Steven : SQL에 대한 매개 변수가 아닙니다. 문자열 연결 대신 자리 표시 자 (물음표)가 있어야합니다. 그리고 SQL에서는 자리 표시 자로 테이블 이름을 지정할 수 없습니다. 이것은 순수한 SQL 주입 취약점-원래 문제입니다.
Jonathan Leffler

@Steven : '매개 변수'라는 용어가 너무 자주 오버로드되었을 수 있습니다. : D
Jonathan Leffler

6

버퍼 오버 플로우는 SQL 주입이 아닙니다.

매개 변수화 된 쿼리는 SQL 주입에 대해 안전함을 보장합니다. 그들은 SQL 서버에 버그 형태의 악용 가능성이 없다는 것을 보장하지는 않지만 그것을 보장하는 것은 없습니다.


2

권한이 테이블 수준에 있어야하므로 모양이나 형식에 관계없이 동적 SQL을 사용하는 경우 데이터가 안전하지 않습니다. 예, 특정 쿼리에서 인젝션 공격의 유형과 양을 제한했지만 사용자가 시스템에 접근 할 수있는 방법을 찾아 내고 내부 사용자가 액세스해서는 안되는 항목에 액세스하는 경우 사용자가 얻을 수있는 액세스를 제한하지는 않습니다. 사기를 저 지르거나 판매를 위해 개인 정보를 훔치는 명령. 모든 유형의 동적 SQL은 위험한 관행입니다. 비 동적 저장 프로 시저를 사용하는 경우 프로 시저 수준에서 권한을 설정할 수 있으며 사용자는 프로 시저에 정의 된 것 외에는 아무것도 할 수 없습니다 (물론 시스템 관리자 제외).


따라서 여기서 교훈은 동적 SQL을 사용해야하는 경우 저장 프로 시저 내에서만 사용해야한다는 것입니다. +1 좋은 조언!
Steven A. Lowe

1
아니요-저장된 procs의 동적 SQL은 확인되지 않은 데이터를 동적 쿼리에 삽입하여 SQL 주입 결함을 여전히 유발할 수 있습니다.
Bill Karwin

여기서 교훈은 절대 동적 SQl을 사용하지 않는 것입니다
HLGEM

@HLGEM-맞습니다. 자동차는 교통 사고에 연루되어 있으므로 절대로 자동차를 사용해서는 안됩니다.
Bill Karwin

그러나 저장된 proc의 동적 SQL은 저장된 proc 소유자의 권한으로 실행되는 정적 SQL과는 달리 호출자의 권한으로 (기본적으로) 실행됩니다. 이것은 중요한 차이점입니다.
HTTP 410

1

저장된 proc이 오버플로 / 잘림을 통한 특수 유형의 SQL 삽입에 취약 할 수 있습니다. 여기에서 데이터 잘림으로 인젝션 활성화를 참조하세요.

http://msdn.microsoft.com/en-us/library/ms161953.aspx


기사를 자세히 읽어 보면 SQL Server의 매개 변수 컬렉션을 사용하면이 공격을 방지 할 수 있음을 알 수 있습니다. 그리고 이것이 "매개 변수화 된 쿼리"의 일반적인 정의입니다. DBMS의 매개 변수 컬렉션을 사용합니다.
HTTP 410

1

매개 변수를 사용하면 문자열을 쉽게 저장할 수 있으며 정책이없는 경우 사용자 이름이라고 말하면 "); drop table users;-"

이것은 그 자체로 아무런 해를 끼치 지 않을 것이지만, 당신은 그 날짜가 당신의 애플리케이션에서 어디에서 어떻게 사용되는지 더 잘 알고 있습니다 (예를 들어, 쿠키에 저장되고, 나중에 다른 일을하기 위해 검색 됨).


1

예를 들어 동적 SQL을 실행할 수 있습니다.

DECLARE @SQL NVARCHAR(4000);
DECLARE @ParameterDefinition NVARCHAR(4000);

SELECT  @ParameterDefinition = '@date varchar(10)'

SET @SQL='Select CAST(@date AS DATETIME) Date'

EXEC sp_executeSQL @SQL,@ParameterDefinition,@date='04/15/2011'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.