SQL注入攻擊的危害性很大。在講解其防止辦法以前,數據庫管理員有必要先了解一下其攻擊的原理。這有利於管理員採起有針對性的防治措施。web
1、 SQL注入攻擊的簡單示例。sql
statement := "SELECT * FROM Users WHERE Value= " + a_variable + "數據庫
上面這條語句是很普通的一條SQL語句,他主要實現的功能就是讓用戶輸入一個員工編號而後查詢處這個員工的信息。可是若這條語句被不法攻擊者改裝事後,就可能成爲破壞數據的黑手。如攻擊者在輸入變量的時候,輸入如下內容SA001’;drop table c_order--。那麼以上這條SQL語句在執行的時候就變爲了SELECT * FROM Users WHERE Value= ‘SA001’;drop table c_order--。編程
這條語句是什麼意思呢?‘SA001’後面的分號表示一個查詢的結束和另外一條語句的開始。c_order後面的雙連字符 指示當前行餘下的部分只是一個註釋,應該忽略。若是修改後的代碼語法正確,則服務器將執行該代碼。系統在處理這條語句時,將首先執行查詢語句,查到用戶編號爲SA001 的用戶信息。而後,數據將刪除表C_ORDER(若是沒有其餘主鍵等相關約束,則刪除操做就會成功)。只要注入的SQL代碼語法正確,便沒法採用編程方式來檢測篡改。所以,必須驗證全部用戶輸入,並仔細檢查在您所用的服務器中執行構造 SQL命令的代碼。安全
2、 SQL注入攻擊原理。服務器
可見SQL注入攻擊的危害性很大。在講解其防止辦法以前,數據庫管理員有必要先了解一下其攻擊的原理。這有利於管理員採起有針對性的防治措施。網絡
SQL注入是目前比較常見的針對數據庫的一種攻擊方式。在這種攻擊方式中,攻擊者會將一些惡意代碼插入到字符串中。而後會經過各類手段將該字符串傳遞到SQLServer數據庫的實例中進行分析和執行。只要這個惡意代碼符合SQL語句的規則,則在代碼編譯與執行的時候,就不會被系統所發現。數據庫設計
SQL注入式攻擊的主要形式有兩種。一是直接將代碼插入到與SQL命令串聯在一塊兒並使得其以執行的用戶輸入變量。上面筆者舉的例子就是採用了這種方法。因爲其直接與SQL語句捆綁,故也被稱爲直接注入式攻擊法。二是一種間接的攻擊方法,它將惡意代碼注入要在表中存儲或者做爲原書據存儲的字符串。在存儲的字符串中會鏈接到一個動態的SQL命令中,以執行一些惡意的SQL代碼。工具
注入過程的工做方式是提早終止文本字符串,而後追加一個新的命令。如以直接注入式攻擊爲例。就是在用戶輸入變量的時候,先用一個分號結束當前的語句。而後再插入一個惡意SQL語句便可。因爲插入的命令可能在執行前追加其餘字符串,所以攻擊者經常用註釋標記「—」來終止注入的字符串。執行時,系統會認爲此後語句位註釋,故後續的文本將被忽略,不背編譯與執行。測試
3、 SQL注入式攻擊的防治。
既然SQL注入式攻擊的危害這麼大,那麼該如何來防治呢?下面這些建議或許對數據庫管理員防治SQL注入式攻擊有必定的幫助。
一、 普通用戶與系統管理員用戶的權限要有嚴格的區分。
若是一個普通用戶在使用查詢語句中嵌入另外一個Drop Table語句,那麼是否容許執行呢?因爲Drop語句關係到數據庫的基本對象,故要操做這個語句用戶必須有相關的權限。在權限設計中,對於終端用戶,即應用軟件的使用者,沒有必要給他們數據庫對象的創建、刪除等權限。那麼即便在他們使用SQL語句中帶有嵌入式的惡意代碼,因爲其用戶權限的限制,這些代碼也將沒法被執行。故應用程序在設計的時候,最好把系統管理員的用戶與普通用戶區分開來。如此能夠最大限度的減小注入式攻擊對數據庫帶來的危害。
二、 強迫使用參數化語句。
若是在編寫SQL語句的時候,用戶輸入的變量不是直接嵌入到SQL語句。而是經過參數來傳遞這個變量的話,那麼就能夠有效的防治SQL注入式攻擊。也就是說,用戶的輸入絕對不可以直接被嵌入到SQL語句中。與此相反,用戶的輸入的內容必須進行過濾,或者使用參數化的語句來傳遞用戶輸入的變量。參數化的語句使用參數而不是將用戶輸入變量嵌入到SQL語句中。採用這種措施,能夠杜絕大部分的SQL注入式攻擊。不過惋惜的是,如今支持參數化語句的數據庫引擎並很少。不過數據庫工程師在開發產品的時候要儘可能採用參數化語句。
三、 增強對用戶輸入的驗證。
整體來講,防治SQL注入式攻擊能夠採用兩種方法,一是增強對用戶輸入內容的檢查與驗證;二是強迫使用參數化語句來傳遞用戶輸入的內容。在SQLServer數據庫中,有比較多的用戶輸入內容驗證工具,能夠幫助管理員來對付SQL注入式攻擊。測試字符串變量的內容,只接受所需的值。拒絕包含二進制數據、轉義序列和註釋字符的輸入內容。這有助於防止腳本注入,防止某些緩衝區溢出攻擊。測試用戶輸入內容的大小和數據類型,強制執行適當的限制與轉換。這即有助於防止有意形成的緩衝區溢出,對於防治注入式攻擊有比較明顯的效果。
如可使用存儲過程來驗證用戶的輸入。利用存儲過程能夠實現對用戶輸入變量的過濾,如拒絕一些特殊的符號。如以上那個惡意代碼中,只要存儲過程把那個分號過濾掉,那麼這個惡意代碼也就沒有用武之地了。在執行SQL語句以前,能夠經過數據庫的存儲過程,來拒絕接納一些特殊的符號。在不影響數據庫應用的前提下,應該讓數據庫拒絕包含如下字符的輸入。如分號分隔符,它是SQL注入式攻擊的主要幫兇。如註釋分隔符。註釋只有在數據設計的時候用的到。通常用戶的查詢語句中沒有必要註釋的內容,故能夠直接把他拒絕掉,一般狀況下這麼作不會發生意外損失。把以上這些特殊符號拒絕掉,那麼即便在SQL語句中嵌入了惡意代碼,他們也將毫無做爲。
故始終經過測試類型、長度、格式和範圍來驗證用戶輸入,過濾用戶輸入的內容。這是防止SQL注入式攻擊的常見而且行之有效的措施。
四、 多多使用SQL Server數據庫自帶的安全參數。
爲了減小注入式攻擊對於SQL Server數據庫的不良影響,在SQLServer數據庫專門設計了相對安全的SQL參數。在數據庫設計過程當中,工程師要儘可能採用這些參數來杜絕惡意的SQL注入式攻擊。
如在SQL Server數據庫中提供了Parameters集合。這個集合提供了類型檢查和長度驗證的功能。若是管理員採用了Parameters這個集合的話,則用戶輸入的內容將被視爲字符值而不是可執行代碼。即便用戶輸入的內容中含有可執行代碼,則數據庫也會過濾掉。由於此時數據庫只把它看成普通的字符來處理。使用Parameters集合的另一個優勢是能夠強制執行類型和長度檢查,範圍之外的值將觸發異常。若是用戶輸入的值不符合指定的類型與長度約束,就會發生異常,並報告給管理員。如上面這個案例中,若是員工編號定義的數據類型爲字符串型,長度爲10個字符。而用戶輸入的內容雖然也是字符類型的數據,可是其長度達到了20個字符。則此時就會引起異常,由於用戶輸入的內容長度超過了數據庫字段長度的限制。
五、 多層環境如何防治SQL注入式攻擊?
在多層應用環境中,用戶輸入的全部數據都應該在驗證以後才能被容許進入到可信區域。未經過驗證過程的數據應被數據庫拒絕,並向上一層返回一個錯誤信息。實現多層驗證。對無目的的惡意用戶採起的預防措施,對堅決的攻擊者可能無效。更好的作法是在用戶界面和全部跨信任邊界的後續點上驗證輸入。如在客戶端應用程序中驗證數據能夠防止簡單的腳本注入。可是,若是下一層認爲其輸入已經過驗證,則任何能夠繞過客戶端的惡意用戶就能夠不受限制地訪問系統。故對於多層應用環境,在防止注入式攻擊的時候,須要各層一塊兒努力,在客戶端與數據庫端都要採用相應的措施來防治SQL語句的注入式攻擊。
六、 必要的狀況下使用專業的漏洞掃描工具來尋找可能被攻擊的點。
使用專業的漏洞掃描工具,能夠幫助管理員來尋找可能被SQL注入式攻擊的點。不過漏洞掃描工具只能發現攻擊點,而不可以主動起到防護SQL注入攻擊的做用。固然這個工具也常常被攻擊者拿來使用。如攻擊者能夠利用這個工具自動搜索攻擊目標並實施攻擊。爲此在必要的狀況下,企業應當投資於一些專業的漏洞掃描工具。一個完善的漏洞掃描程序不一樣於網絡掃描程序,它專門查找數據庫中的SQL注入式漏洞。最新的漏洞掃描程序能夠查找最新發現的漏洞。因此憑藉專業的工具,能夠幫助管理員發現SQL注入式漏洞,並提醒管理員採起積極的措施來預防SQL注入式攻擊。若是攻擊者可以發現的SQL注入式漏洞數據庫管理員都發現了並採起了積極的措施堵住漏洞,那麼攻擊者也就無從下手了。
防止注入式攻擊方法:
1.不要或儘可能少拼接sql,禁止用戶輸入敏感字符
2.注意對用戶輸入的數據進行檢查
3.sql參數使用參數化形式(parameter)
一、對string參數進行Replace("'","''") or Replace("'","")
示例sql語句:string sql = "select * from [users] where [name]='"+ name.Replace("'","") +"'";
注意sql語句中[name]=''兩個單引號不可缺
二、對int參數進行int.Parse()
示例sql語句:string sql = "select * from [users] where [id]="+ int.Parse(id).ToString();
1、什麼是SQL注入式攻擊? 所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙服務器執行惡意的SQL命令。在某些表單中,用戶輸入的內容直接用來構造(或者影響)動態SQL命令,或做爲存儲過程的輸入參數,這類表單特別容易受到SQL注入式攻擊。常見的SQL注入式攻擊過程類如: ⑴ 某個ASP.NET Web應用有一個登陸頁面,這個登陸頁面控制着用戶是否有權訪問應用,它要求用戶輸入一個名稱和密碼。 ⑵ 登陸頁面中輸入的內容將直接用來構造動態的SQL命令,或者直接用做存儲過程的參數。下面是ASP.NET應用構造查詢的一個例子: System.Text.StringBuilder query = new System.Text.StringBuilder( "SELECT * from Users WHERE login = '") .Append(txtLogin.Text).Append("' AND password='") .Append(txtPassword.Text).Append("'"); ⑶ 攻擊者在用戶名字和密碼輸入框中輸入"'或'1'='1"之類的內容。 ⑷ 用戶輸入的內容提交給服務器以後,服務器運行上面的ASP.NET代碼構造出查詢用戶的SQL命令,但因爲攻擊者輸入的內容很是特殊,因此最後獲得的SQL命令變成:SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'。 ⑸ 服務器執行查詢或存儲過程,將用戶輸入的身份信息和服務器中保存的身份信息進行對比。 ⑹ 因爲SQL命令實際上已被注入式攻擊修改,已經不能真正驗證用戶身份,因此係統會錯誤地受權給攻擊者。 若是攻擊者知道應用會將表單中輸入的內容直接用於驗證身份的查詢,他就會嘗試輸入某些特殊的SQL字符串篡改查詢改變其原來的功能,欺騙系統授予訪問權限。 系統環境不一樣,攻擊者可能形成的損害也不一樣,這主要由應用訪問數據庫的安全權限決定。若是用戶的賬戶具備管理員或其餘比較高級的權限,攻擊者就可能對數據庫的表執行各類他想要作的操做,包括添加、刪除或更新數據,甚至可能直接刪除表。 2、如何防範? 好在要防止ASP.NET應用被SQL注入式攻擊闖入並非一件特別困難的事情,只要在利用表單輸入的內容構造SQL命令以前,把全部輸入內容過濾一番就能夠了。過濾輸入內容能夠按多種方式進行。 ⑴ 對於動態構造SQL查詢的場合,可使用下面的技術: 第一:替換單引號,即把全部單獨出現的單引號改爲兩個單引號,防止攻擊者修改SQL命令的含義。再來看前面的例子,「SELECT * from Users WHERE login = ''' or ''1''=''1' AND password = ''' or ''1''=''1'」顯然會獲得與「SELECT * from Users WHERE login = '' or '1'='1' AND password = '' or '1'='1'」不一樣的結果。 第二:刪除用戶輸入內容中的全部連字符,防止攻擊者構造出類如「SELECT * from Users WHERE login = 'mas' -- AND password =''」之類的查詢,由於這類查詢的後半部分已經被註釋掉,再也不有效,攻擊者只要知道一個合法的用戶登陸名稱,根本不須要知道用戶的密碼就能夠順利得到訪問權限。 第三:對於用來執行查詢的數據庫賬戶,限制其權限。用不一樣的用戶賬戶執行查詢、插入、更新、刪除操做。因爲隔離了不一樣賬戶可執行的操做,於是也就防止了本來用於執行SELECT命令的地方卻被用於執行INSERT、UPDATE或DELETE命令。 ⑵ 用存儲過程來執行全部的查詢。SQL參數的傳遞方式將防止攻擊者利用單引號和連字符實施攻擊。此外,它還使得數據庫權限能夠限制到只容許特定的存儲過程執行,全部的用戶輸入必須聽從被調用的存儲過程的安全上下文,這樣就很難再發生注入式攻擊了。 ⑶ 限制表單或查詢字符串輸入的長度。若是用戶的登陸名字最多隻有10個字符,那麼不要承認表單中輸入的10個以上的字符,這將大大增長攻擊者在SQL命令中插入有害代碼的難度。 ⑷ 檢查用戶輸入的合法性,確信輸入的內容只包含合法的數據。數據檢查應當在客戶端和服務器端都執行——之因此要執行服務器端驗證,是爲了彌補客戶端驗證機制脆弱的安全性。 在客戶端,攻擊者徹底有可能得到網頁的源代碼,修改驗證合法性的腳本(或者直接刪除腳本),而後將非法內容經過修改後的表單提交給服務器。所以,要保證驗證操做確實已經執行,惟一的辦法就是在服務器端也執行驗證。你可使用許多內建的驗證對象,例如RegularExpressionValidator,它們可以自動生成驗證用的客戶端腳本,固然你也能夠插入服務器端的方法調用。若是找不到現成的驗證對象,你能夠經過CustomValidator本身建立一個。 ⑸ 將用戶登陸名稱、密碼等數據加密保存。加密用戶輸入的數據,而後再將它與數據庫中保存的數據比較,這至關於對用戶輸入的數據進行了「消毒」處理,用戶輸入的數據再也不對數據庫有任何特殊的意義,從而也就防止了攻擊者注入SQL命令。System.Web.Security.FormsAuthentication類有一個HashPasswordForStoringInConfigFile,很是適合於對輸入數據進行消毒處理。 ⑹ 檢查提取數據的查詢所返回的記錄數量。若是程序只要求返回一個記錄,但實際返回的記錄卻超過一行,那就看成出錯處理。