flawopen.com/SQL-Injection/Gespeicherte Prozeduren
Schützen gespeicherte Prozeduren vor SQL-Injection?
Nein — das ist ein verbreiteter Irrtum. Eine gespeicherte Prozedur schützt nur, wenn sie intern Parameter bindet. Verkettet sie ihre Eingaben zu einer Abfragezeichenfolge und führt diese mit EXEC oder sp_executesql aus, ist sie genauso anfällig wie eine Verkettung in der Anwendung.
-- 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;
-- 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;
Warum dieser Irrtum verbreitet ist
„Verwenden Sie gespeicherte Prozeduren“ wird oft pauschal als Lösung für SQL-Injection genannt. Das trifft zu, wenn die Prozedur Werte in einer normalen Abfrage als gebundene Parameter übergibt. Erzeugt sie dynamisches SQL mit EXEC und verkettet nicht vertrauenswürdige Werte, entsteht dasselbe Risiko erneut. Wenn dynamisches SQL nötig ist, binden Sie Werte mit sp_executesql. Tabellen- und Spaltennamen lassen sich nicht als Werte binden; ordnen Sie erlaubte Optionen über eine Allowlist festen Bezeichnern zu.
Häufige Fragen
Ja. sp_executesql unterstützt Parameter: deklarieren Sie diese und übergeben Sie Werte getrennt (zum Beispiel EXEC sp_executesql @sql, N'@id INT', @id = @UserId). Verketten Sie keine Werte in @sql. Für dynamische Tabellen- oder Spaltennamen ist eine strikte Allowlist nötig, da Bezeichner keine bindbaren Werte sind.