Sql server之sql注入篇

SQL Injectionhtml

關於sql注入的危害在這裏就很少作介紹了,相信你們也知道其中的厲害關係。這裏有一些sql注入的事件你們感興趣能夠看一下sql

 

防範sql注入的方法無非有如下幾種:shell

1.使用類型安全的SQL參數
2.使用參數化輸入存儲過程
3.使用參數集合與動態SQL
4.輸入濾波
5.過濾LIKE條款的特殊字符編程

...若是有遺漏的也歡迎園子的大大們指教。安全

Sample:服務器

var Shipcity;
ShipCity = Request.form ("ShipCity");
var sql = "select * from OrdersTable where ShipCity = '" + ShipCity + "'";

上面是一個簡單的sql注入示例架構

用戶將被提示輸入一個市縣名稱。若是用戶輸入 Redmond,則查詢將由與下面內容類似的腳本組成:測試

SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond'

可是,假定用戶輸入如下內容:編碼

Redmond'; drop table OrdersTable--spa

此時,腳本將組成如下查詢:

1 SELECT * FROM OrdersTable WHERE ShipCity = 'Redmond';drop table OrdersTable--'

 

分號 (;) 表示一個查詢的結束和另外一個查詢的開始。雙連字符 (--) 指示當前行餘下的部分是一個註釋,應該忽略。若是修改後的代碼語法正確,則服務器將執行該代碼。SQL Server 處理該語句時,SQL Server 將首先選擇 OrdersTable 中的全部記錄(其中 ShipCity 爲 Redmond)。而後,SQL Server 將刪除 OrdersTable。

只要注入的 SQL 代碼語法正確,便沒法採用編程方式來檢測篡改。所以,必須驗證全部用戶輸入,並仔細檢查在您所用的服務器中執行構造 SQL 命令的代碼。本主題中的如下各部分說明了編寫代碼的最佳作法。

下面就介紹一下經常使用的幾種防止sql注入的方法:
 
始終經過測試類型、長度、格式和範圍來驗證用戶輸入。實現對惡意輸入的預防時,請注意應用程序的體系結構和部署方案。請注意,設計爲在安全環境中運行的程序可能會被複制到不安全的環境中。如下建議應被視爲最佳作法:
  • 對應用程序接收的數據不作任何有關大小、類型或內容的假設。例如,您應該進行如下評估:

    • 若是一個用戶在須要郵政編碼的位置無心中或惡意地輸入了一個 10 MB 的 MPEG 文件,應用程序會作出什麼反應?

    • 若是在文本字段中嵌入了一個 DROP TABLE 語句,應用程序會作出什麼反應?

  • 測試輸入的大小和數據類型,強制執行適當的限制。這有助於防止有意形成的緩衝區溢出。

  • 測試字符串變量的內容,只接受所需的值。拒絕包含二進制數據、轉義序列和註釋字符的輸入內容。這有助於防止腳本注入,防止某些緩衝區溢出攻擊。

  • 使用 XML 文檔時,根據數據的架構對輸入的全部數據進行驗證。

  • 毫不直接使用用戶輸入內容來生成 Transact-SQL 語句。

  • 使用存儲過程來驗證用戶輸入。

  • 在多層環境中,全部數據都應該在驗證以後才容許進入可信區域。未經過驗證過程的數據應被拒絕,並向前一層返回一個錯誤。

  • 實現多層驗證。對無目的的惡意用戶採起的預防措施對堅決的攻擊者可能無效。更好的作法是在用戶界面和全部跨信任邊界的後續點上驗證輸入。

    例如,在客戶端應用程序中驗證數據能夠防止簡單的腳本注入。可是,若是下一層認爲其輸入已經過驗證,則任何能夠繞過客戶端的惡意用戶就能夠不受限制地訪問系統。

  • 毫不串聯未驗證的用戶輸入。字符串串聯是腳本注入的主要輸入點。

  • 在可能據以構造文件名的字段中,不接受下列字符串:AUX、CLOCK$、COM1 到 COM八、CON、CONFIG$、LPT1 到 LPT八、NUL 以及 PRN。

若是可能,拒絕包含如下字符的輸入。

 

輸入字符

在 Transact-SQL 中的含義

;

查詢分隔符。

'

字符數據字符串分隔符。

--

註釋分隔符。

/* ... */

註釋分隔符。服務器不對 /* 和 */ 之間的註釋進行處理。

xp_

用於目錄擴展存儲過程的名稱的開頭,如 xp_cmdshell

 

注:驗證輸入是最被經常使用和聯想到的,可是我的感受這種方式不但代碼顯得肥胖,並且效率不是很好

2.使用類型安全的 SQL 參數

SQL Server 中的 Parameters 集合提供了類型檢查和長度驗證。若是使用 Parameters 集合,則輸入將被視爲文字值而不是可執行代碼。使用 Parameters 集合的另外一個好處是能夠強制執行類型和長度檢查。範圍之外的值將觸發異常。如下代碼段顯示瞭如何使用 Parameters 集合:

 
1 SqlDataAdapter myCommand = new SqlDataAdapter("AuthorLogin", conn);
2 myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
3 SqlParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id",
4      SqlDbType.VarChar, 11);
5 parm.Value = Login.Text;

在此示例中,@au_id 參數被視爲文字值而不是可執行代碼。將對此值進行類型和長度檢查。若是 @au_id 值不符合指定的類型和長度約束,則將引起異常。

 

存儲過程若是使用未篩選的輸入,則可能容易受 SQL Injection 攻擊。例如,如下代碼容易受到攻擊:

 
  SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure '" + Login.Text + "'", conn); 

若是使用存儲過程,則應使用參數做爲存儲過程的輸入。

注:在鄙人如今的項目中,這種方法應用最爲普遍

3.在動態 SQL 中使用參數集合

若是不能使用存儲過程,您仍可以使用參數,如如下代碼示例所示:

 
1 SqlDataAdapter myCommand = new SqlDataAdapter(
2 "SELECT au_lname, au_fname FROM Authors WHERE au_id = @au_id", conn);
3 SQLParameter parm = myCommand.SelectCommand.Parameters.Add("@au_id", 
4                         SqlDbType.VarChar, 11);
5 Parm.Value = Login.Text;

注:和第二種雷同,這種方法是爲了補充方法2存在,由於每每在不少時候業務簡單不須要用proc的時候,能夠用這種方法

4.篩選輸入

篩選輸入能夠刪除轉義符,這也可能有助於防止 SQL 注入。但因爲可引發問題的字符數量很大,所以這並非一種可靠的防禦方法。如下示例可搜索字符串分隔符。

 
1 private string SafeSqlLiteral(string inputSQL)
2 {
3   return inputSQL.Replace("'", "''");
4 }

 

注:Filtering Input有種相似方法1

5.LIKE 子句

請注意,若是要使用 LIKE 子句,還必須對通配符字符進行轉義:

 
1  
2 s = s.Replace("[", "[[]");
3 s = s.Replace("%", "[%]");
4 s = s.Replace("_", "[_]");

注:針對like子句,在使用時的效率這裏就很少說了,總之要慎用了。

 

 

以上全部方法及其註釋高亮顯示部分,均爲本人愚見,若是對方法有補充或者對高亮部分有不一樣意見的,歡迎你們給出意見,共同進步.

本文是在借鑑MSDN的前提下加了一些本身的理解與意見, 轉載請注入出處。 thx.

 

if您看了這篇博客。對您有所幫助,請不要吝嗇您的「推薦」,您的推薦將是我最大的動力。有問題的話能夠評論交流。

相關文章
相關標籤/搜索