Microsoft SQL Server
動的SQL
サーチ…
文字列として提供されたSQL文を実行する
場合によっては、stringに配置されたSQLクエリを実行する必要があります。 EXEC、EXECUTE、またはシステム・プロシージャsp_executesqlは、stringとして指定されたSQL問合せを実行できます。
sp_executesql N'SELECT * FROM sys.objects'
-- or
sp_executesql @stmt = N'SELECT * FROM sys.objects'
-- or
EXEC sp_executesql N'SELECT * FROM sys.objects'
-- or
EXEC('SELECT * FROM sys.columns')
-- or
EXECUTE('SELECT * FROM sys.tables')
このプロシージャは、文のテキストとして提供されるSQL問合せと同じ結果セットを戻します。 sp_executesqlは、文字列リテラル、変数/パラメータ、または偶数式として提供されるSQLクエリを実行できます。
declare @table nvarchar(40) = N'product items'
EXEC(N'SELECT * FROM ' + @table)
declare @sql nvarchar(40) = N'SELECT * FROM ' + QUOTENAME(@table);
EXEC sp_executesql @sql
@table変数の特殊文字をエスケープするには、QUOTENAME関数が必要です。 @table変数にスペース、角かっこなどの特殊文字が含まれていると、この関数がなければ構文エラーが発生します。
異なるユーザーとして実行される動的SQL
AS USER = 'データベースユーザーの名前'を使用して、異なるユーザーとしてSQLクエリを実行できます。
EXEC(N'SELECT * FROM product') AS USER = 'dbo'
SQLクエリはdboデータベースユーザーの下で実行されます。 dboユーザーに適用されるすべての権限チェックは、SQLクエリでチェックされます。
動的SQLを使用したSQLインジェクション
動的クエリは
SET @sql = N'SELECT COUNT(*) FROM AppUsers WHERE Username = ''' + @user + ''' AND Password = ''' + @pass + ''''
EXEC(@sql)
ユーザー変数の値がmyusername '' OR 1 = 1 - の場合 、次のクエリが実行されます。
SELECT COUNT(*)
FROM AppUsers
WHERE Username = 'myusername' OR 1=1 --' AND Password = ''
変数@usernameの値の最後にあるコメントは、クエリの後続部分をコメントアウトし、条件1 = 1が評価されます。このクエリによって返された少なくとも1人のユーザーがそこをチェックするアプリケーションは、0より大きいカウントを返し、ログインは成功します。
この方法を使用すると、攻撃者は有効なユーザー名とパスワードを知らなくてもアプリケーションにログインできます。
パラメータを使用した動的SQL
注入やエスケープの問題を避けるために、動的SQLクエリは次のようなパラメータで実行する必要があります。
SET @sql = N'SELECT COUNT(*) FROM AppUsers WHERE Username = @user AND Password = @pass
EXEC sp_executesql @sql, '@user nvarchar(50), @pass nvarchar(50)', @username, @password
2番目のパラメータは、そのタイプでクエリで使用されるパラメータのリストです。このリストには、パラメータ値として使用される変数が提供されています。
sp_executesqlは特殊文字をエスケープし、SQLクエリを実行します。