簡體   English   中英

我對參數化SQL與具有動態SQL的存儲過程感到困惑,即它們是相同的嗎?

[英]I'm confused About Parameterized SQL vs Stored Procedures Having Dynamic SQL i.e. are they the same?

我創建了以下過程:

 CREATE PROC dynamicColumnsWithCheck
 (
    @colName VARCHAR(MAX),
    @colCheck VARCHAR(MAX),
    @condition VARCHAR(MAX)
 )

 AS

 BEGIN

    DECLARE @sqlString NVARCHAR(MAX)

    SET @sqlString = N'SELECT ' + @colName + ' FROM Student WHERE ' + @colCheck + ' = ''' + @condition + ''''

    EXEC sp_executesql @sqlString

 END

它對我來說很完美,但是我的問題是,這是參數化的SQL嗎? 還是危險的動態SQL? 在搜索和學習了一些有關SQL注入的知識之后,我對該過程的安全性感到困惑。

它可以像這樣注入:

  declare @sqlstring varchar(MAX)
  declare @colName varchar(500) = 'Password'
  declare @colCheck varchar(500) = 'StudentName' 
  declare @condition varchar(500) = 'Zeebo'' or ''''='''

  SET @sqlString = N'SELECT ' + @colName + ' FROM Student WHERE ' + @colCheck + ' = ''' + @condition + ''''


  PRINT (@sqlString)

結果:

從學生那里選擇密碼StudentName ='Zeebo'或``=''

始終將''=''設置為true,因此它將返回所有內容,這對於用戶密碼來說將是災難。

避免SQL注入的簡單方法是將用戶變量與整個語句視為一個單獨的單元。 例如,您可以使用QuoteName來包裝用戶變量,因此動態部分將僅被解析為輸入,並且不會影響整個查詢。

例如:

declare @sqlstring varchar(MAX)
      declare @colName varchar(500) = 'Password'
      declare @colCheck varchar(500) = 'StudentName' 
      declare @condition varchar(500) = 'Zeebo'' or ''''='''

      SET @sqlString = N'SELECT ' + QUOTENAME(@colName) + ' FROM Student WHERE ' + QUOTENAME(@colCheck) + ' = ''' + QUOTENAME(@condition) + ''''

返回使用先前的注入方法,@ condition的用戶輸入將被視為PURE字符串,而不在構建最終的@sqlString中發揮任何作用。 結果將是:

從學生那里選擇[密碼] [StudentName] ='[Zeebo'或''=']'

這甚至不是正確的sql語句。

這是參數化的SQL嗎? 還是危險的動態SQL?

都是。

SQL Server參數只能用於替換查詢中的離散 -您無法參數化對象標識符(例如表名,列名)或子句(例如WHERE謂詞),因此Dynamic SQL仍然是一回事。

由於這個問題,許多人開始使用諸如Linq-to-Entities(實體框架)之類的ORM,該ORM以一種允許在運行時安全構造查詢的方式安全地為您生成SQL。

在Linq中更改WHERE子句比嘗試生成自己的SQL容易得多:

嘗試通過自己生成SQL,在下面進行此查詢-它的可讀性,可維護性會大大降低,並且只需直接使用級聯直接生成SQL,您就有注入漏洞的風險:

String GetUserName(String emailAddress) {

    IQueryable<User> query = database.Users;
    query = query.Where( u => u.Email == emailAddress );

    if( !userHasPermissionToViewAllUsers ) {
        query = query.Where( u => u.UserId == currentUserUserId );
    }

    return query.FirstOrDefault()?.UserName;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM