flawopen.com/SQL 인젝션/저장 프로시저
저장 프로시저는 SQL 인젝션을 막나요?
참고 페이지
핵심 답변
아닙니다. 흔한 오해입니다. 저장 프로시저는 내부에서 매개변수를 바인딩할 때만 보호 기능을 제공합니다. 입력을 연결해 쿼리 문자열을 만들고 EXEC 또는 sp_executesql로 실행하면 애플리케이션의 문자열 연결과 같은 위험이 있습니다.
위험 — 값을 동적 SQL에 연결
-- SQL Server T-SQL; dbo.Users.Id is NVARCHAR(50).
CREATE PROCEDURE dbo.GetUser
@UserId NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(MAX) =
N'SELECT Id FROM dbo.Users WHERE Id = N'''
+ @UserId + N'''';
EXEC(@sql);
END;
안전 — sp_executesql로 매개변수 바인딩
-- SQL Server T-SQL; same illustrative schema.
CREATE PROCEDURE dbo.GetUser
@UserId NVARCHAR(50)
AS
BEGIN
DECLARE @sql NVARCHAR(MAX) =
N'SELECT Id FROM dbo.Users WHERE Id = @id';
EXEC sys.sp_executesql
@stmt = @sql,
@params = N'@id NVARCHAR(50)',
@id = @UserId;
END;
이 오해가 흔한 이유
“저장 프로시저를 사용하라”는 SQL 인젝션의 만능 해결책처럼 반복됩니다. 일반 쿼리에서 값을 바인딩 매개변수로 전달할 때만 맞는 말입니다. EXEC로 동적 SQL을 만들고 신뢰할 수 없는 값을 연결하면 같은 위험이 다시 생깁니다. 동적 SQL이 필요하면 sp_executesql로 값을 바인딩하세요. 테이블 및 열 이름은 값처럼 바인딩할 수 없으므로 허용된 선택지를 고정 식별자에 매핑하는 엄격한 allowlist를 사용하세요.
자주 묻는 질문
sp_executesql은 안전하게 사용할 수 있나요?
가능합니다. sp_executesql은 매개변수를 지원합니다. 매개변수를 선언하고 값을 별도로 전달하세요(예: EXEC sp_executesql @sql, N'@id INT', @id = @UserId). 값을 @sql에 연결하지 마세요. 동적 테이블명이나 열 이름은 바인딩할 수 없으므로 엄격한 allowlist를 사용하세요.