當應用程序使用輸入內容來構造動態 SQL 語句以訪問數據庫時,會發生 SQL 注入攻擊。如果代碼使用存儲過程,而這些存儲過程作爲包含未篩選的用戶輸入的字符串來傳遞,也會發生 SQL 注入攻擊。SQL 注入可能導致攻擊者能夠使用應用程序登錄在數據庫中執行命令。如果應用程序使用特權過高的帳戶連接到數據庫,這種問題會變得很嚴重。
注意 傳統的安全措施(如使用 SSL 和 IPSec)不能防止 SQL 注入攻擊。
防止 SQL 注入
使用下列對策來防止 SQL 注入攻擊:
•限制輸入。
•使用類型安全的 SQL 參數。
限制輸入
驗證輸入內容的類型、長度、格式和範圍。如果您不希望獲得數值,則不要接受它們。應該考慮輸入內容來自何處。如果它來自受信任源,而且您知道已針對該來源執行過徹底的輸入驗證,則可以選擇在數據訪問代碼中忽略數據驗證。如果數據來自不受信任源或者用於深層防禦,則數據訪問方法和組件應該驗證輸入。
使用類型安全的 SQL 參數
SQL 中的 Parameters 集合提供類型檢查和長度驗證。如果您使用 Parameters 集合,則輸入內容將被視爲文本值,SQL 不會將其視爲可執行代碼。使用 Parameters 集合還有一個好處,那就是可以強制進行類型和長度檢查。超出範圍的值會觸發異常。這是深層防禦的一個有力示例。
要點 SSL 不能防止 SQL 注入。對於任何應用程序來說,如果它在沒有正確的輸入驗證和適當的數據訪問技術的情況下訪問數據庫,都很容易受到 SQL 注入攻擊。
儘可能使用存儲過程,並使用 Parameters 集合來調用它們。
結合使用 Parameters 集合和存儲過程
下面的代碼片斷闡釋了 Parameters 集合的用法:
SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn); myCommand.SelectCommand.CommandType = CommandType.StoredProcedure; SqlParameter parm = myCommand.SelectCommand.Parameters.Add( "@au_id", SqlDbType.VarChar, 11); parm.Value = Login.Text;
在本例中,@au_id 參數被視爲文本值,而非可執行代碼。另外,還針對參數進行了類型和長度檢查。在上例中,輸入值不能長於 11 個字符。如果數據不遵循由參數定義的類型或長度,就會生成異常。
請注意,使用存儲過程不一定會防止 SQL 注入。重要的是結合使用參數和存儲過程。如果不使用參數,則在存儲過程使用未篩選的輸入內容時,它們很容易受到 SQL 注入攻擊。例如,下面的代碼片斷很容易受到攻擊:
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure '" + Login.Text + "'", conn);
要點 如果使用存儲過程,請確保同時使用參數。
結合使用 Parameters 集合和動態 SQL
如果您不能使用存儲過程,仍可以使用參數,如下面的代碼片斷所示:
SqlDataAdapter myCommand = new SqlDataAdapter( "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn); SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11); parm.Value = Login.Text;
使用參數批處理
通常會產生如下誤解:如果將幾個 SQL 語句連接在一起,以便在單個往返中向服務器發送一批語句,則不能使用參數。但是,如果您能確保參數名不重複,則可以使用這種技術。通過在 SQL 文本連接過程中,向每個參數名中添加一個數字或其他某個唯一值,可以方便地執行此操作。
使用篩選例程
用來防止 SQL 注入攻擊的另一種方法是開發篩選例程,以便向具有特殊 SQL 含義的字符添加轉義符,如單撇號字符。下面的代碼片斷闡釋了一個用來添加轉義符的篩選例程:
private string SafeSqlLiteral(string inputSQL) { return inputSQL.Replace("'", "''"); }
這種例程存在着一定的問題,而且您不應完全依賴它們,因爲攻擊者可以使用 ASCII 十六進制字符來回避檢查。但是應該篩選輸入內容,並將其作爲深層防禦策略的一部分。
注意 不要依賴篩選輸入。
使用 LIKE 子句
請注意,如果您使用 LIKE 子句,通配符仍需要轉義符。下面的代碼片斷闡釋了這種技術:
s = s.Replace("[", "[[]"); s = s.Replace("%", "[%]"); s = s.Replace("_", "[_]");
轉載於:https://www.cnblogs.com/lanchong/archive/2010/08/03/1791380.html