Programing

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

lottogame 2020. 10. 6. 07:44
반응형

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


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

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

물론 웹 응용 프로그램이 안전한지 확인하기 위해 고려해야 할 다른 고려 사항이 있습니다 (사용자 입력 및 모든 항목 삭제 등). 이제 SQL 주입을 생각하고 있습니다. MsSQL 2005 및 2008이 기본 데이터베이스이기 때문에 특히 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 표현식을 동적으로 작성하는 것과 같은 다른 구문의 경우 더 복잡한 문제입니다.


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

  • 매개 변수를 허용하는 저장된 proc과 같은 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을 주입하려는 시도를 제거해야합니다.

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

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

If @p1 is selected from a drop-down list it is a potential sql-injection attack vector;

If @p1 is formulated programmatically w/out the ability of the user to intervene then it is not a potential sql-injection attack vector


A buffer overflow is not SQL injection.

Parametrized queries guarantee you are safe against SQL injection. They don't guarantee there aren't possible exploits in the form of bugs in your SQL server, but nothing will guarantee that.


Your data is not safe if you use dynamic sql in any way shape or form because the permissions must be at the table level. Yes you have limited the type and amount of injection attack from that particular query, but not limited the access a user can get if he or she finds a way into the system and you are completely vunerable to internal users accessing what they shouldn't in order to commit fraud or steal personal information to sell. Dynamic SQL of any type is a dangerous practice. If you use non-dynamic stored procs, you can set permissions at the procesdure level and no user can do anything except what is defined by the procs (except system admins of course).


It is possible for a stored proc to be vulnerable to special types of SQL injection via overflow/truncation, see: Injection Enabled by Data Truncation here:

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


Just remember that with parameters you can easily store the string, or say username if you don't have any policies, "); drop table users; --"

This in itself won't cause any harm, but you better know where and how that date is used further on in your application (e.g. stored in a cookie, retrieved later on to do other stuff.


You can run dynamic sql as example

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

반응형