Web安全之SQL注入攻擊

什麼是SQL注入式攻擊?sql

所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙服務器執行惡意的SQL命令。在某些表單中,用戶輸入的內容直接用來構造(或者影響)動態SQL命令,或做爲存儲過程的輸入參數,這類表單特別容易受到SQL注入式攻擊。常見的SQL注入式攻擊過程類如:數據庫

⑴ 某個應用有一個登陸頁面,這個登陸頁面控制着用戶是否有權訪問應用,它要求用戶輸入一個名稱和密碼。安全

⑵ 登陸頁面中輸入的內容將直接用來構造動態的SQL命令,或者直接用做存儲過程的參數。例如:服務器

SELECT from Users WHERE login = 'username' AND password 'password'
加密

⑶ 攻擊者在用戶名字和密碼輸入框中輸入"'或'1'='1"之類的內容。spa

⑷ 用戶輸入的內容提交給服務器以後,服務器運行上面的代碼構造出查詢用戶的SQL命令,但因爲攻擊者輸入的內容很是特殊,因此最後獲得的SQL命令變成:.net

SELECT from Users WHERE login = '' or '1'='1' AND password '' or '1'='1'
unix

⑸ 服務器執行查詢或存儲過程,將用戶輸入的身份信息和服務器中保存的身份信息進行對比。code

⑹ 因爲SQL命令實際上已被注入式攻擊修改,已經不能真正驗證用戶身份,因此係統會錯誤地受權給攻擊者。orm

若是攻擊者知道應用會將表單中輸入的內容直接用於驗證身份的查詢,他就會嘗試輸入某些特殊的SQL字符串篡改查詢改變其原來的功能,欺騙系統授予訪問權限。

系統環境不一樣,攻擊者可能形成的損害也不一樣,這主要由應用訪問數據庫的安全權限決定。若是用戶的賬戶具備管理員或其餘比較高級的權限,攻擊者就可能對數據庫的表執行各類他想要作的操做,包括添加、刪除或更新數據,甚至可能直接刪除表。

例如,儘管SELECT是隻讀的,但不表明SQL只能這樣。SQL使用分號表示結束,若是輸入沒有正確過濾,就沒有什麼能阻止咱們在字符串後構造與查詢無關的指令。

咱們指望得sql語句:

SELECT  email, passwd, login_id, full_name  
FROM  members  
WHERE  email =  'xxxxx' ;
由於參數xxxxx變成了x'; DROP TABLE members;,獲得下面語句:

SELECT  email, passwd, login_id, full_name  
FROM  members  
WHERE  email =  'x' DROP  TABLE  members; ';
若是咱們 瞭解members表的局部結構,甚至能夠往表members裏增長成員:

SELECT  email, passwd, login_id, full_name  
FROM  members  
WHERE  email =  'x' ;  
         INSERT  INTO  members ( 'email' , 'passwd' , 'login_id' , 'full_name' )   
         VALUES  ( 'steve@unixwiz.net' , 'hello' , 'steve' , 'Steve Friedl' );'

如何防範?

好在要防止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參數的傳遞方式將防止攻擊者利用單引號和連字符實施攻擊。此外,它還使得數據庫權限能夠限制到只容許特定的存儲過程執行,全部的用戶輸入必須聽從被調用的存儲過程的安全上下文,這樣就很難再發生注入式攻擊了。如:

不安全版

1
2
Statement s =  connection .createStatement();  
ResultSet rs = s.executeQuery( "SELECT email FROM member WHERE name = "  + formField);

安全版

1
2
3
PreparedStatement ps =  connection .prepareStatement( "SELECT email FROM member WHERE name = ?" );
ps.setString(1, formField);
ResultSet rs = ps.executeQuery();

⑶ 限制表單或查詢字符串輸入的長度。若是用戶的登陸名字最多隻有10個字符,那麼不要承認表單中輸入的10個以上的字符,這將大大增長攻擊者在SQL命令中插入有害代碼的難度。

⑷ 檢查用戶輸入的合法性,確信輸入的內容只包含合法的數據。數據檢查應當在客戶端和服務器端都執行——之因此要執行服務器端驗證,是爲了彌補客戶端驗證機制脆弱的安全性。

在客戶端,攻擊者徹底有可能得到網頁的源代碼,修改驗證合法性的腳本(或者直接刪除腳本),而後將非法內容經過修改後的表單提交給服務器。所以,要保證驗證操做確實已經執行,惟一的辦法就是在服務器端也執行驗證。你可使用許多內建的驗證對象,例如 RegularExpressionValidator,它們可以自動生成驗證用的客戶端腳本,固然你也能夠插入服務器端的方法調用。若是找不到現成的驗證對象,你能夠經過CustomValidator本身建立一個。

⑸ 將用戶登陸名稱、密碼等數據加密保存。加密用戶輸入的數據,而後再將它與數據庫中保存的數據比較,這至關於對用戶輸入的數據進行了"消毒"處理,用戶輸入的數據再也不對數據庫有任何特殊的意義,從而也就防止了攻擊者注入SQL命令。 System.Web.Security.FormsAuthentication類有一個 HashPasswordForStoringInConfigFile,很是適合於對輸入數據進行消毒處理。

⑹ 檢查提取數據的查詢所返回的記錄數量。若是程序只要求返回一個記錄,但實際返回的記錄卻超過一行,那就看成出錯處理。

相關文章
相關標籤/搜索