sourcetip

매개 변수는 정말로 SQL 주입을 방지하기에 충분합니까?

fileupload 2023. 6. 7. 23:05
반응형

매개 변수는 정말로 SQL 주입을 방지하기에 충분합니까?

저는 동료들과 SO 모두에게 SQL 쿼리, 특히 .NET 애플리케이션에서 매개 변수를 사용하는 것의 장점에 대해 설교해 왔습니다.저는 SQL 주입 공격에 대한 면역을 부여하는 것을 약속하기까지 했습니다.

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

물론 웹 애플리케이션의 안전성을 보장하기 위해 고려해야 할 다른 사항도 있습니다(사용자 입력 검사 등). 하지만 지금은 SQL 주입을 생각하고 있습니다.저는 특히 MsSQL 2005와 2008에 대한 공격에 관심이 있습니다. 왜냐하면 그것들은 저의 기본 데이터베이스이기 때문입니다. 그러나 모든 데이터베이스는 흥미롭습니다.

편집: 매개 변수와 매개 변수화된 쿼리가 무엇을 의미하는지 명확히 설명합니다.매개 변수를 사용한다는 것은 sql 쿼리를 문자열로 작성하는 대신 "변수"를 사용한다는 것을 의미합니다.
이렇게에: 이게하는대신에:

SELECT * FROM Table WHERE Name = 'a name'

다음 작업을 수행합니다.

SELECT * FROM Table WHERE Name = @Name

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

자리 표시자는 주입을 방지하기에 충분합니다.버퍼 오버플로에 여전히 노출되어 있을 수 있지만, 이는 SQL 주입과는 완전히 다른 공격 방식입니다(공격 벡터는 SQL 구문이 아니라 이진).전달된 매개 변수는 모두 올바르게 이스케이프되므로 공격자가 "활성" SQL로 처리되는 데이터를 전달할 수 있는 방법이 없습니다.

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

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

즉, 입력을 사용하여 다음과 같은 값을 설정하는 경우security_level그러면 누군가가 당신의 시스템에서 관리자가 되어 자유롭게 사용할 수 있습니다.그러나 이는 기본적인 입력 검증일 뿐 SQL 주입과는 아무런 관련이 없습니다.

아니요, 검증되지 않은 데이터를 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 표현식을 동적으로 작성하는 것과 같은 다른 구문은 더 복잡한 문제입니다.

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

  • 매개 변수를 수락하는 저장 프로시저와 같은 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();
}

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

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

EDIT: 매개 변수 @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 주입 공격 벡터가 아닙니다.

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

매개 변수화된 쿼리를 사용하면 SQL 주입으로부터 안전합니다.SQL 서버에 버그 형태로 악용될 가능성이 없다고 보장하지는 않지만, 그 어떤 것도 보장하지는 않습니다.

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

저장된 proc는 오버플로/잘라내기를 통해 특수 유형의 SQL 주입에 취약할 수 있습니다. 여기서는 "데이터 잘라내기에 의한 주입 활성화:

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

매개 변수를 사용하여 문자열을 쉽게 저장하거나 정책이 없으면 사용자 이름을 ";"; 테이블 사용자 삭제; --"라고 말할 수 있습니다.

이 자체는 아무런 해를 끼치지 않지만 응용 프로그램에서 해당 날짜가 어디서 어떻게 사용되는지 알고 있어야 합니다(예: 쿠키에 저장된 후 나중에 다른 작업을 위해 검색됨).

예를 들어 동적 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'

언급URL : https://stackoverflow.com/questions/306668/are-parameters-really-enough-to-prevent-sql-injections

반응형