1. 程式人生 > >Java程式設計師從笨鳥到菜鳥之(一百零二)sql注入攻擊詳解(三)sql注入解決辦法

Java程式設計師從笨鳥到菜鳥之(一百零二)sql注入攻擊詳解(三)sql注入解決辦法

               

在前面的部落格中,我們詳細介紹了:

      我們瞭解了sql注入原理和sql注入過程,今天我們就來了解一下sql注入的解決辦法。怎麼來解決和防範sql注入,由於本人主要是搞java web開發的小程式設計師,所以這裡我只講一下有關於java web的防止辦法。其實對於其他的,思路基本相似。下面我們先從web應用程式的角度來看一下如何避免sql注入:

1、普通使用者與系統管理員使用者的許可權要有嚴格的區分。

  如果一個普通使用者在使用查詢語句中嵌入另一個Drop Table語句,那麼是否允許執行呢?由於Drop語句關係到資料庫的基本物件,故要操作這個語句使用者必須有相關的許可權。在許可權設計中,對於終端使用者,即應用軟體的使用者,沒有必要給他們資料庫物件的建立、刪除等許可權。那麼即使在他們使用

SQL語句中帶有嵌入式的惡意程式碼,由於其使用者許可權的限制,這些程式碼也將無法被執行。故應用程式在設計的時候,最好把系統管理員的使用者與普通使用者區分開來。如此可以最大限度的減少注入式攻擊對資料庫帶來的危害。

2、 強迫使用引數化語句。

  如果在編寫SQL語句的時候,使用者輸入的變數不是直接嵌入到SQL語句。而是通過引數來傳遞這個變數的話,那麼就可以有效的防治SQL注入式攻擊。也就是說,使用者的輸入絕對不能夠直接被嵌入到SQL語句中。與此相反,使用者的輸入的內容必須進行過濾,或者使用引數化的語句來傳遞使用者輸入的變數。引數化的語句使用引數而不是將使用者輸入變數嵌入到SQL語句中。採用這種措施,可以杜絕大部分的

SQL注入式攻擊。不過可惜的是,現在支援引數化語句的資料庫引擎並不多。不過資料庫工程師在開發產品的時候要儘量採用引數化語句。

3加強對使用者輸入的驗證。

  總體來說,防治SQL注入式攻擊可以採用兩種方法,一是加強對使用者輸入內容的檢查與驗證;二是強迫使用引數化語句來傳遞使用者輸入的內容。在SQLServer資料庫中,有比較多的使用者輸入內容驗證工具,可以幫助管理員來對付SQL注入式攻擊。測試字串變數的內容,只接受所需的值。拒絕包含二進位制資料、轉義序列和註釋字元的輸入內容。這有助於防止指令碼注入,防止某些緩衝區溢位攻擊。測試使用者輸入內容的大小和資料型別,強制執行適當的限制與轉換。這即有助於防止有意造成的緩衝區溢位,對於防治注入式攻擊有比較明顯的效果。

4、 多多使用SQL Server資料庫自帶的安全引數。

  為了減少注入式攻擊對於SQL Server資料庫的不良影響,在SQLServer資料庫專門設計了相對安全的SQL引數。在資料庫設計過程中,工程師要儘量採用這些引數來杜絕惡意的SQL注入式攻擊。

5、 多層環境如何防治SQL注入式攻擊?

  在多層應用環境中,使用者輸入的所有資料都應該在驗證之後才能被允許進入到可信區域。未通過驗證過程的資料應被資料庫拒絕,並向上一層返回一個錯誤資訊。實現多層驗證。對無目的的惡意使用者採取的預防措施,對堅定的攻擊者可能無效。更好的做法是在使用者介面和所有跨信任邊界的後續點上驗證輸入。如在客戶端應用程式中驗證資料可以防止簡單的指令碼注入。但是,如果下一層認為其輸入已通過驗證,則任何可以繞過客戶端的惡意使用者就可以不受限制地訪問系統。故對於多層應用環境,在防止注入式攻擊的時候,需要各層一起努力,在客戶端與資料庫端都要採用相應的措施來防治SQL語句的注入式攻擊。

6、必要的情況下使用專業的漏洞掃描工具來尋找可能被攻擊的點。

  使用專業的漏洞掃描工具,可以幫助管理員來尋找可能被SQL注入式攻擊的點。不過漏洞掃描工具只能發現攻擊點,而不能夠主動起到防禦SQL注入攻擊的作用。當然這個工具也經常被攻擊者拿來使用。如攻擊者可以利用這個工具自動搜尋攻擊目標並實施攻擊。為此在必要的情況下,企業應當投資於一些專業的漏洞掃描工具。一個完善的漏洞掃描程式不同於網路掃描程式,它專門查詢資料庫中的SQL注入式漏洞。最新的漏洞掃描程式可以查詢最新發現的漏洞。所以憑藉專業的工具,可以幫助管理員發現SQL注入式漏洞,並提醒管理員採取積極的措施來預防SQL注入式攻擊。如果攻擊者能夠發現的SQL注入式漏洞資料庫管理員都發現了並採取了積極的措施堵住漏洞,那麼攻擊者也就無從下手了。

        上面主要是介紹了在web應用程式中對sql注入的大體解決思路,下面我們就根據java web應用程式的特徵來具體說明一下如何解決在java web應用程式中的sql注入問題。

1.採用預編譯語句集,它內建了處理SQL注入的能力,只要使用它的setXXX方法傳值即可。

使用好處:

(1).程式碼的可讀性和可維護性.

(2).PreparedStatement盡最大可能提高效能.

(3).最重要的一點是極大地提高了安全性.

String sql= "select * from users where username=? and password=?;          PreparedStatement preState = conn.prepareStatement(sql);          preState.setString(1, userName);          preState.setString(2, password);          ResultSet rs = preState.executeQuery(); 

原理:sql注入只對sql語句的準備(編譯)過程有破壞作用,而PreparedStatement已經準備好了,執行階段只是把輸入串作為資料處理,而不再對sql語句進行解析,準備,因此也就避免了sql注入問題.

2.使用正則表示式過濾傳入的引數

正則表示式:

private String CHECKSQL = “^(.+)\\sand\\s(.+)|(.+)\\sor(.+)\\s$”;

判斷是否匹配:

Pattern.matches(CHECKSQL,targerStr);

下面是具體的正則表示式:

檢測SQL meta-characters的正則表示式 :

/(\%27)|(\’)|(\-\-)|(\%23)|(#)/ix

修正檢測SQL meta-characters的正則表示式 :/((\%3D)|(=))[^\n]*((\%27)|(\’)|(\-\-)|(\%3B)|(:))/i

典型的SQL 注入攻擊的正則表示式 :/\w*((\%27)|(\’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix

檢測SQL注入,UNION查詢關鍵字的正則表示式 :/((\%27)|(\’))union/ix(\%27)|(\’)

檢測MS SQL Server SQL注入攻擊的正則表示式:

/exec(\s|\+)+(s|x)p\w+/ix

等等…..

 其實可以簡單的使用replace方法也可以實現上訴功能:

 public static String TransactSQLInjection(String str)          {                return str.replaceAll(".*([';]+|(--)+).*", " ");          } 

3.字串過濾

比較通用的一個方法:

(||之間的引數可以根據自己程式的需要新增)

public static boolean sql_inj(String str){String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";String inj_stra[] = split(inj_str,"|");for (int i=0 ; i < inj_stra.length ; i++ ){if (str.indexOf(inj_stra[i])>=0){return true;}}return false;}

4.jsp中呼叫該函式檢查是否包函非法字元

防止SQL從URL注入:

sql_inj.java程式碼:

package sql_inj;import java.net.*;import java.io.*;import java.sql.*;import java.text.*;import java.lang.String;public class sql_inj{public static boolean sql_inj(String str){String inj_str = "'|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";//這裡的東西還可以自己新增String[] inj_stra=inj_str.split("\\|");for (int i=0 ; i < inj_stra.length ; i++ ){if (str.indexOf(inj_stra[i])>=0){return true;}}return false;}} 

5.JSP頁面新增客戶端判斷程式碼:

使用javascript在客戶端進行不安全字元遮蔽

功能介紹:檢查是否含有”‘”,”\\”,”/”

引數說明:要檢查的字串

返回值:0:是1:不是

函式名是

function check(a){return 1;fibdn = new Array (”‘” ,”\\”,”/”);i=fibdn.length;j=a.length;for (ii=0; ii<i; ii++){ for (jj=0; jj<j; jj++){ temp1=a.charAt(jj);temp2=fibdn[ii];if (tem’; p1==temp2){ return 0; }}}return 1;}

 關於安全性,本文可總結出一下幾點:

          1.要對使用者輸入的內容保持警惕。          2.只在客戶端進行輸入驗證等於沒有驗證。          3.永遠不要把伺服器錯誤資訊暴露給使用者。

註明:本文參考了網上一些資源,寫的時候沒有記下出處,所以無法註明,並且本文僅供讀者學習所用,請不要做有些違反法律的事情,一旦發生,與本人無關

------------------------------------------------------------------------------------------------------------------------  廣告:我參加了2012年度IT部落格大賽,希望大家能多多支援http://blog.51cto.com/contest2012/3545281

------------------------------------------------------------------------------------------------------------