[제목] SQL Injection (3) - Stored Procedure에서의 SQL Injection
지금까지의 SQL Injection 관련 아티클에서 설명한 바와 같이, C#에서 SQL문을 문자열 병합 (string concatenation)으로 처리하는 것은 SQL Injection을 야기하는 주요 원인이 되며, 따라서 SqlParameter를 사용한 Parameterized Query를 이용해야 함을 알 수 있었다. 그러면 다음과 같이 SQL Stored Procedure를 C#에서 호출하는 것은 어떤 문제가 있을 수 있을까?
/* C# */ public void CallWrongSP() { string name = "Park"; using (SqlConnection conn = new SqlConnection(connStr)) { conn.Open(); // Parameterized Query : SP SqlCommand cmd = new SqlCommand("sp_Call", conn); cmd.CommandType = CommandType.StoredProcedure; SqlParameter pInput = new SqlParameter("@name", name); cmd.Parameters.Add(pInput); // Run SP var rs = cmd.ExecuteReader(); while (rs.Read()) { Debug.WriteLine(rs[0]); } } }
언뜻 보기에, 이 C# 코드는 아무런 문제 없어 보이는데, 실제 저장 프로시져(Stored Procedure, SP)를 보지 않고 C# 코드만 따진다면, 문제될 것이 없다. 하지만, 이 C# 코드가 호출하는 Stored Procedure가 다음과 같다면, SQL Injection이 일어날 수 있다.
-- -- SQL Injection 문제가 있는 Stored Procedure -- CREATE PROC [dbo].[sp_Call] ( @name nvarchar(max) ) AS BEGIN DECLARE @sql nvarchar(max) SET @sql = 'SELECT * FROM users WHERE name=''' + @name + '''' -- EXEC @sql exec sp_executesql @sql END;
이 SP를 자세히 보면, 전달받은 파라미터 @name의 값을 SELECT 문에 다시 문자열 병합으로 연결하고 있다. 이렇게 병합된 Dynamic SQL문은 EXEC 혹은 sp_executesql 을 사용하여 실행되는데, 여기서는 sp_executesql을 EXEC와 같이 사용하고 있다 . TSQL문에서 EXEC 와 sp_executesql의 차이점은 EXEC (Execute)는 문자열 병합으로 생성된 Dynamic SQL문을 직접 실행하는데 사용되고, sp_executesql은 EXEC 보다 향상된 기능으로 TSQL문에서 파라미터가 되는 부분을 직접 문자열 병합하여 사용하지 않고 C#의 SqlParameter사용예와 같이 파라미터화하여 전달할 수 있다는 것이다. 따라서 위와 같이 문자열 병합 대신 아래 예제와 같이 @name 부분을 다시 파리미터로 만들어 sp_executesql 의 세번째 파라미터에 넣을 수 있다.
-- -- SQL Injection 문제가 없는 Stored Procedure -- CREATE PROC [dbo].[sp_Call] ( @name nvarchar(max) ) AS BEGIN DECLARE @sql nvarchar(max) SET @sql = 'SELECT * FROM users WHERE name = @paraName' exec sp_executesql @sql, N'@paraName nvarchar(max)', @name END;
위의 예제에서 @paraName이라는 임의의 파라미터를 만들고 이를 sp_executesql의 두번째 Argument에서 @paraName nvarchar(max)와 같이 파라미터 데이타형을 지정한 후, 세번째 Argument에 해당 파라미터값을 전달하면, sp_executesql은 @name값을 파라미터 하나로 인식하여 SQL Injection을 방지하게 된다. 비록 sp_executesql이 파라미터가 없이 (위의 잘못된 예제처럼) Dyanmic SQL문을 실행할 수는 있지만, 항상 (파라미터가 있는 경우) 해당 파라미터를 지정하여 문장을 수행해야 SQL Injection의 위험으로부터 벗어날 수가 있다.
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.