文獻標識碼: A
文章編號: 0258-7998(2013)04-0137-04
SQL注入攻擊是一種常見的互聯(lián)網攻擊手段,,它具有易操作,、強隱蔽、高危害和難檢測等特點,。由于SQL注入攻擊的對象是Web服務器后臺的數據庫,,而數據庫往往存放重要的用戶數據或業(yè)務數據,因而SQL注入攻擊的后果影響非常嚴重,。特別對銀行,、證券、電信,、移動,、政府以及電子商務企業(yè)等后臺數據庫。一旦遭受SQL注入而導致數據纂改或機密數據丟失,,在經濟角度和社會角度都將產生惡劣的影響,。因此檢測和防范SQL注入是軟件安全領域的重要課題,具有極高的研究價值和意義,。
常見的Web應用系統(tǒng)架構如圖1所示,其中包括Web服務器及后臺數據庫,。在Web服務器上部署Web服務,用戶使用瀏覽器通過Http或Https協(xié)議與Web服務器進行交互,。常稱之為B/S架構,。
在該架構中,Web服務器向用戶提供各種應用服務,這些服務都涉及到與數據庫的交互,,即伴執(zhí)行SQL語句,。如果Web應用系統(tǒng)設計或實現不合理,將可能導致用戶對數據庫執(zhí)行的SQL語句偏離系統(tǒng)設計的預期,從而引發(fā)安全事故,。
Java程序運行在JVM中,,因為具有與平臺無關的特點,這種完全面向對象開發(fā)的語言廣泛應用在Web系統(tǒng)的設計中。針對Java源代碼的SQL注入攻擊檢測進行研究,,對于提高Web應用系統(tǒng)的安全性具有重要意義,。
本文介紹了SQL注入原理、目前的檢測方法以及Java代碼對數據庫操作的三種代碼結構,。針對Java執(zhí)行SQL語句的特點,,重點提出一種基于抽象語法樹進行SQL執(zhí)行路徑檢測的SQL注入檢測算法;在Web 應用程序發(fā)布前進行深入靜態(tài)分析和檢查,,從而提高Web應用系統(tǒng)的安全性,。算例分析和在實際Web系統(tǒng)中的應用結果表明,本文提出的SQL注入檢測算法具有高檢測率和低誤報率,。
1 相關研究工作
SQL注入漏洞最早在2000年左右被提出,,其后學者們對SQL注入的檢測和防護展開了一系列的研究。
典型的一種SQL注入例子如下:
(1)用戶登錄Web應用系統(tǒng)時,,需要進行身份認證,,主要輸入用戶名和密碼兩個變量v_usr和v_pwd;
(2)Web系統(tǒng)執(zhí)行合法性檢查的SQL語句為:“Select * from users where username=‘”+v_usr+“’and password=‘”+ v_pwd+“’”,如果用戶登錄時用戶取為‘admin’ or 1=1--,,那么合法性檢查的SQL語句等效于Select * from users where username=‘ admin’ or 1=1;
顯然,,用戶名取‘admin’ or 1=1--時,無論密碼輸入多少,,都可以登錄系統(tǒng),。
SQL注入的檢測和防護方式目前主要有兩大類,一是系統(tǒng)上線前檢測,,也稱為靜態(tài)檢測,;二是系統(tǒng)在線運行防御,也稱為動態(tài)檢測,。
動態(tài)檢測方式是一種黑盒檢測方法,對上線的系統(tǒng)進行SQL漏洞掃描,,編制SQL注入攻擊腳本對Web系統(tǒng)進行試探,,通過檢查Http的回應報文內容來判斷是否發(fā)生SQL注入攻擊,從而確定是否存在SQL注入漏洞,。AppScan等工具可執(zhí)行此類安全檢測,。
靜態(tài)檢測方法是一種白盒檢測方法[1],通過靜態(tài)語法解析查找Web 應用代碼中可能引發(fā)SQL注入的環(huán)節(jié),,在Web應用發(fā)布前檢查代碼質量,。Fotify等工具可執(zhí)行此類安全檢測。參考文獻[2-3]給出一種動態(tài)生成SQL語句進行類型正確性檢查的方法來檢測是否存在SQL注入,,該方法的的缺點在于只能檢測句法結構或語句類型出現異常的SQL注入問題,。參考文獻[4]提出一種自動推理機的方法對添加了輸入值后的SQL語句進行檢查,該方法的缺點在于只能檢測出重言式的SQL注入攻擊。此外,,還有一些學者采用機器學習算法對SQL注入漏洞進行檢測[5],,這一類檢測方法的檢測率和誤報率往往依賴于訓練集的大小。
2 Java源代碼靜態(tài)掃描分析思路
程序靜態(tài)分析指在不執(zhí)行程序的情況下,,通過自動掃描代碼發(fā)現隱含的程序隱患[6],,具備執(zhí)行速度快、效率高等優(yōu)點,。對源代碼進行靜態(tài)分析時借鑒編譯技術的詞法分析和語法分析,。源代碼進行靜態(tài)分析掃描原理如圖2所示。
Java程序與數據庫之間的交互主要通過Java數據庫連接JDBC進行,。其數據庫操作涉及與數據庫建立連接,、發(fā)送SQL指令、處理返回結果,、斷開數據庫連接4個步驟,。
具體實現上主要涉及的Java類有Connection類、DriverManager類,、Statement類,、ResultSet類、PreparedStatement類和callableStatement類,。在代碼實現上往往有3種實現方式:
(1) 常規(guī)方式
//函數 DB_SQL(SQL語句)
Connection con=DriverManager. getConnection(參數URL,,參數用戶名,參數密碼);
Statement stat = con.createStatement();
ResultSet rs = stat.executeQuery("SQL語句");(或者executeUpdate /execute /executeBatch)
//此處為rs的處理代碼
rs.close(); stat.close(); con.close();
Java采用常規(guī)方式訪問數據庫,,每次都需要進行建立連接,,再執(zhí)行SQL語句,最后釋放連接,。由于建立連接過程一般比較耗時(一般需要幾十毫秒至幾百毫秒之間),,而且Statement對象每次執(zhí)行SQL語句的解析和編譯也比較耗時,如果涉及如下循環(huán)使用情況,,則代碼的執(zhí)行效率將會比較低下,。為此,對于需要頻繁建立數據庫連接的情況,,可以采用連接池方式進行優(yōu)化,;對于需要頻繁執(zhí)行相似SQL語句的情況,則可采用預編譯方式進行優(yōu)化,。
while(N次)
{
DB_SQL(SQL語句);
}
(2) 預編譯方式
采用常規(guī)方式執(zhí)行SQL語句時,,DBMS需要對SQL語句進行解析和編譯;而采用預編譯方式時,,DBMS只在第一次對SQL語句進行解析和編譯,。相比前者,,后者更難注入SQL。原因在于,,PreparedStatement對象執(zhí)行SQL語句前,,需要設置“?”號對應的變量,例如ps.setInt(1,變量v1),、ps.setLong(2,變量v2) 表示SQL語句中第一個“?”號是int型,、值為“變量v1”;這樣在安全性上相當于增加了一個類型匹配,。
Connection con=DriverManager.getConnection(參數URL,,參數用戶名,參數密碼);
while(N次)
{
PreparedStatement ps = con.prepareStatement(帶若干“?”號的SQL語句);
ps.setXX(“,?”的序號, 變量); //XX包括int double等
ResultSet rs = ps.executeQuery();(或者executeUpdate /execute /executeBatch)
//此處為rs的處理代碼
rs.close();
}
ps.close(); con.close();
(3) 連接池方式
連接池(Connection Pool)是設計模式中資源池(Resource Pool)的一種具體應用,,主要解決資源頻繁分配和釋放所帶來的性能問題。其基本思想是預先建立一個數據庫連接池,,在該連接池中預先存放一定數量的連接,,當需要建立數據庫連接時,并非新建一個數據庫連接,,而是從連接池中取出一個連接對象,,然后對該連接對象進行參數設置和使用,使用完畢后,,并不釋放該連接,,而是將連接對象的參數復位并回收。
采用連接池的應用開發(fā)方式與常規(guī)方式的代碼結構類似,。區(qū)別是常規(guī)方式的連接對象在需要時才從堆中動態(tài)分配空間與數據庫建立連接,,使用完畢后即斷開連接,等待Java的GC垃圾回收器發(fā)現該對象不再需要后,將回收連接對象的內存空間,;而采用連接池方式,則是在連接池中預先建立一個若干數據的連接對象,,需要使用時才從連接池中取出一個連接對象(不是臨時創(chuàng)建,因此效率高),,使用完畢后,,并不斷開連接,而是將該連接對象歸還給對象池,。通過一個“借用”和“歸還”的方式使得可以高效地對付頻繁的數據庫訪問操作。目前常用的連接池主要有C3PO,、BoneCP,、DBCP、Proxool等,。
綜上所述,無論采用哪一種數據庫操作方式,,Java源代碼中可能出現SQL注入漏洞的代碼執(zhí)行過程中,一定經過executeQuery、executeUpdate,、execute 或executeBatch函數,。本文提出的SQL檢測算法,正是通過定位這些函數并以此為分析SQL注入隱患的切入點,,跟蹤這些函數的參數或參數表達式,。如果這些參數表達式最終能追溯到某個特定的對象(如HttpServletRequest),則可以肯定這條路徑將可能存在SQL注入隱患,。
3 Java源代碼SQL注入檢測算法
抽象語法樹AST(Abstract Syntax Tree)是程序源代碼的抽象語法結構的樹狀表現形式,,樹上的每個節(jié)點表示源代碼中的一種結構,AST的好處在于不依賴于具體的方法和語言細節(jié),。對于源代碼的文法分析,,首先進行詞法分析,將源代碼中所有字符串從前至后逐個字符進行掃描,,并對每個“單詞”進行標識,。這些“單詞”主要包括Java語言中的關鍵字、標識符,、運算符和分隔符等,。然后進行語法分析,將這些識別出來的“單詞”序列分解成各類Java語法單位,。
根據源代碼靜態(tài)分析掃描原理,,結合Java 1.6的文法定義,本文提出的SQL注入檢測算法通過對源代碼的詞法和語法分析,,生成相應的抽象語法樹,,定義規(guī)則,根據規(guī)則遍歷抽象語法樹,。
本文提出的檢測算法實現步驟如下:
(1) 遍歷抽象語法樹,尋找METHOD_DECL結點中節(jié)點名為executeQuery或executeUpdate或execute或executeBatch的所有節(jié)點,并將它們保存在哈希表keyNode中,。
(2) 找keyNode中的每一個節(jié)點,確認是否是正確的結點,。首先得到keyNode節(jié)點的前繼表達式,,并得到前繼表達式的返回值類型。若前繼表達式的返回值類型為Java.sql.Statement,,則可確認此結點,,并轉到下一步;若返回值類型不是Java.sql.Statement,,則轉步驟(2),,檢測下一個節(jié)點;
(3) 確認結點,,取得第一個參數作為路徑結點,,分析并跟蹤路徑結點的數據流,。具體為:分析并跟蹤路徑結點表達式為變量表達式;分析并跟蹤路徑結點表達式為方法表達式,;跟蹤退出的準則描述如下:①當所有跟蹤變量均到達常量定值,,則此路徑不會產生SQL注入漏洞,轉步驟(2),;②跟蹤到開始API定義的方法結點,,轉步驟(4)。
(4) 記錄跟蹤到的SQL注入的侵入路徑,,轉步驟(2),,檢測下一個節(jié)點。若keyNode中所有結點都已檢測完成,,則算法終止,。
4 算法實驗
為了驗證本文提出的算法的有效性,以一個Java程序為實驗算例進行分析和說明,,實驗算例代碼如圖3所示,。
在實驗的Java源代碼中,可能產生SQL注入的開始API和結束API(即Java源代碼SQL注入檢測規(guī)則),,具體如表1所示,。
根據SQL注入檢測規(guī)則,利用本文所提出的檢測算法對圖3所示的Java源代碼進行掃描分析,,產生的抽象語法樹如圖4所示,,可發(fā)現SQL注入漏洞,并報告相應的路徑,。
本文提出的SQL注入檢測算法已經成功應用于本單位信息系統(tǒng)的Java源代碼靜態(tài)檢測中,。在新上線運行的某Web系統(tǒng)(約10萬行代碼)靜態(tài)分析中,檢測時間僅為5 s,,檢測準確識別率高達90%,,而誤報率僅有10%;通過實驗和實際系統(tǒng)的測試和驗證,,本文提出的Java源代碼SQL注入靜態(tài)分析算法具有很好的應用效果和前景,。
參考文獻
[1] WILLIAM G J, VIEGAS H J, ORSO A. A classification of SQL injection attacks and countermeasures[C]. Proc. of International Symposium on Secure Software Engineering.2006.
[2] GOULD C, SU Z, DEVANBU P. JDBC checker: a static analysis tool for SQL/JDBC applications[C]. Proceeding of the 26th International conference on Software Engineering(ICSE). Washington D C: IEEE computer Society, 2004.
[3] GOULD C, SU Z, DEVANBU P. Static checking of dynamically generated queries in database applications[C].Proceedings of 26th International Conference on Software Engineering, 2004.
[4] WASSERMANN G, SU Z. An analysis framework for security in Web applications[C]. Proceedings of the FSE Work shop on Specification and Verification of Component Based System, 2004.
[5] HUANG Y W, HUANG S K, LIN T P, et al. Web application security assessment by fault injection and behavior monitoring[C]. Porceeding of the 11th International World Wide Conferecne, 2002.
[6] 張卓.SQL注入攻擊技術及防范措施研究[D].上海:上海交通大學,2007.