岳 清 郝保水
(北京信息科技大學計算機學院,北京 100101)
基于WEB應用程序的SQL注入防范研究
岳 清 郝保水
(北京信息科技大學計算機學院,北京 100101)
隨著網絡的普及,越來越多的應用系統(tǒng)采用了B/S模式,介紹了SQL注入攻擊的原理以及對Web服務器帶來的危害,并結合Web應用程序開發(fā)給出了若干防范方法,以供開發(fā)Web程序和架設服務器時參考。
SQL注入;正則表達式;存儲過程;PreparedStatement;正則表達式
隨著互聯(lián)網的發(fā)展,越來越多的系統(tǒng)采用基于Web服務的方式,針對Web業(yè)務的攻擊亦在迅猛增長。常見的Web攻擊可分為三類:一是利用WEB 服務器的漏洞進行攻擊,如CGI、緩沖區(qū)溢出;二是利用網頁自身的安全漏洞進行攻擊,如SQL注入、Cookie假冒、認證逃避、非法輸入、強制訪問、隱藏變量篡改等;三是利用僵尸網絡的分布式DOS攻擊,造成網站拒絕服務。在這些安全隱患中,兩種攻擊手段概率最高,它們分別是“跨站點腳本攻擊”和“SQL注入攻擊”。2008年,特別是與金融服務和在線零售業(yè)相關的網站受到的SQL 注入攻擊數(shù)量明顯上升,根據(jù)網絡安全公司WebCohort關于網絡應用程序調查研究報告顯示,有可能受到黑客攻擊的網絡應用程序不少于92%,其中,有60%就有可能遭受SQL 注入攻擊。本文將通過對SQL注入原理的分析來闡述防范SQL注入的方法。
對SQL注入攻擊目前還沒有一種標準的定義,微軟技術中心從兩個方面進行了描述:(1)是一種腳本注入式的攻擊;(2)惡意用戶輸入用來影響被執(zhí)行的SQL腳本。WEB 應用一般是用客戶輸入數(shù)據(jù)來構造SQL 查詢語句,如果程序編寫時,沒有對用戶輸入數(shù)據(jù)的合法性進行判斷,用戶就可以利用某些提交數(shù)據(jù)頁面或修改數(shù)據(jù)頁面里的漏洞,精心構造SQL語句,讓系統(tǒng)執(zhí)行此類特殊的SQL指令,從而獲取一些敏感信息,甚至獲取主機控制權限。 SQL注入是從正常的WWW端口訪問,而且表面看起來跟一般的Web頁面訪問沒什么區(qū)別,所以目前市面的防火墻都不會對SQL注入發(fā)出警報,如果管理員沒查看IIS日志的習慣,可能被入侵很長時間都不會發(fā)覺。
例如,在Web應用程序的登錄頁面中,允許用戶輸入其用戶名(userID)和密碼(psd)兩個參數(shù),應用程序通過user表中進行登錄身份驗證。假設登錄用戶名為:“mike”,密碼為:“mike1980”。則常用的身份驗證語句就變?yōu)椋?/p>
select * from users where userID='mike' and psd='mike1980',正常情況下,如果上述sql查詢返回一條用戶記錄,則說明身份驗證成功;反之,則說明身份驗證失敗。如果分別為userID和psd 兩個參數(shù)賦值:“'abc' or 1=1—”和“abc”,則上述SQL 語句就會變?yōu)椋?/p>
select * from users where userID = 'mike' or 1=1--and psd ='abc'顯然在該語句的兩個判斷條件中,其中有一個恒為真,即1=1,因此身份驗證就會成功。可見攻擊者在不知道有效的用戶名和密碼的情況下就可以通過身份驗證。這就是一種最簡單的SQL注入??梢钥闯鯯QL注入的原理就是將SQL命令通過“嵌入”的方式放入合法的HTTP提交請求中,從而進行非授權或非法的操作。當應用程序使用輸入內容來構造動態(tài)sql語句以訪問數(shù)據(jù)庫時,會發(fā)生SQL注入攻擊。
SQL注入主要的步驟如下:
(1)發(fā)現(xiàn)SQL注入位置;
通過對帶有參數(shù)的動態(tài)網頁地址后附件信息,比較運行結果,判斷該Web應用程序是否可以被注入。
(2)判斷后臺數(shù)據(jù)庫類型;
可以根據(jù)SQL注入不成功的提示信息,分析數(shù)據(jù)庫的類型。 因此要特別注意,編寫程序的時候,要盡量考慮所有可能出現(xiàn)的錯誤并編寫錯誤提示,要避免系統(tǒng)提示。
(3)確定XP_CMDSHELL可執(zhí)行情況;
若當前連接數(shù)據(jù)的帳號具有SA權限,且master.dbo.xp_cmdshell擴展存儲過程(調用此存儲過程可以直接使用操作系統(tǒng)的shell)能夠正確執(zhí)行,則整個計算機可以通過以下幾種方法完全控制,以后的所有步驟都可以省去。
(4)發(fā)現(xiàn)WEB虛擬目錄;
只有找到WEB虛擬目錄,才能確定放置ASP木馬的位置。
(5)上傳ASP木馬;
(6)得到管理員權限。
SQL注入成功后,造成的危害也很嚴重:
(1)Web服務器數(shù)據(jù)庫信息會被竊取。一旦攻擊者通過了SQL注入,可以通過訪問系統(tǒng)數(shù)據(jù)庫master的系統(tǒng)表sysdatabases,猜解出所有的數(shù)據(jù)庫名,再通過對每個庫的系統(tǒng)表Sysobjects的訪問,可以猜解出該庫的所有對象的對象名、對象ID、對象類型、所有者對象的用戶ID、對象狀態(tài)。接下來就可以查看每個對象了,信息就這樣被竊取了。
(2)Web服務器數(shù)據(jù)庫對象受損。SQL注入成功后可在Web服務器執(zhí)行SQL命令,如delete、insert等。如果刪除了表或者庫,那么 Web應用程序的訪問必然會出錯。動態(tài)生成網頁的數(shù)據(jù)庫被通過 SQL注入的方式刪除了,網頁無法生成。這就是常見的網站被“黑”的原因之一。
(3)計算機受控。通過注入,上傳木馬,這是危害最大的一種方式,SQL注入后,若當前連接數(shù)據(jù)的帳號具有SA權限,且可執(zhí)行 master.dbo.xp_cmdshell擴展存儲過程,用xp_cmdshell 向服務器上寫入一個能寫文件的 asp文件,通過該方法即可上傳木馬,被攻擊的計算機就處于被控制狀態(tài)了。
在了解了SQL注入的原理、過程和后果之后,接下來將闡述SQL注入防范方法。在Web項目中合理使用防范SQL注入方法是Web項目設計和開發(fā)者必須要考慮的問題。
目標是過濾輸入中能夠引起SQL注入的字符或單詞。以下的例子是將字符串過濾功能封裝在一個名為sql_inj.java的文件中,在jsp中可以調用該函數(shù)檢查是否包含非法字符。public static boolean sql_inj(String str)
{
String inj_str =
"'|and|exec|insert|select|delete|update|count|*|%|ch r|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;
}
正則表達式,在計算機科學中,是指一個用來描述或者匹配一系列符合某個句法規(guī)則的字符串的單個字符串。在很多文本編輯器或其他工具里,正則表達式通常被用來檢索和/或替換那些符合某個模式的文本內容??梢允褂谜齽t表達式對輸入項進行檢查。
下面是具體的正則表達式:
(1)檢測SQL meta-characters的正則表達式:
/(\%27)|(’)|(--)|(\%23)|(#)/ix
(2)修正檢測SQL meta-characters的正則表達式:
/((\%3D)|(=))[^ ]*((\%27)|(’)|(--)|(\%3B)|(:))/i
(3)典型的 SQL 注入攻擊的正則表達式:
/w*((\%27)|(’))((\%6F)|o|(\%4F))((\%72)|r|(\%52))/ix
(4)檢測SQL注入,UNION查詢關鍵字的正則表達式:
/((\%27)|(’))union/ix(\%27)|(’)
(5)檢測MS SQL Server SQL注入攻擊的正則表達式:
/exec(s|+)+(s|x)pw+/ix
SQL注入的原因就是將SQL命令通過“嵌入”的方式放入合法的HTTP提交請求中。如果使用預編譯語句,傳入的任何內容就不會和原來的語句發(fā)生任何匹配的關系,就用不著對傳入的數(shù)據(jù)做任何過慮。這就是在JDBC應用中,應該始終以PreparedStatement代替Statement的原因。也就是說,在任何時候都不要使用Statement.,凡涉及到執(zhí)行的SQL中有變量時,用JDBC(或者其他數(shù)據(jù)持久層)提供的如:PreparedStatement就可以 。PreparedStatement的優(yōu)點如下:
(1)代碼的可讀性和可維護性。
(2)PreparedStatement盡最大可能提高性能。
(3)最重要的一點是極大地提高了安全性。以下是一段關于PreparedStatement的代碼:
try {
String username =
httpservletrequest.getParameter("username");
String password =
httpservletrequest.getParameter("password");
String sql = "SELECT * FROM users where username=?and password=?";
Connection conn =
ConnectionManager.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1,username);
pstmt.setString(2,password);
ResultSet resultset = pstmt.executeQuery();
} catch (SQLException e) {
e.printStackTrace();
}
運行結果是只要輸入特殊的符號都會以(/? )的形式出現(xiàn),因此 SQL肯定是不會通過的。所以這樣可以簡單又有效的防止SQL的注入。
輸入驗證不是萬能的,比如用過濾字符串的方法拒絕了“delete”字符串的輸入,但攻擊者只需要把該字符串改寫成“DeLetE”等形式就可以避開輸入驗證,并能正常執(zhí)行該SQL語句。所以更重要的一點是必須考慮SQL Server 自身安全性問題。在創(chuàng)建數(shù)據(jù)庫構架時應該考慮以下問題:
(1)數(shù)據(jù)庫賬號的管理:創(chuàng)建低權限賬號;刪除冗余的賬號;保持賬號密碼的高安全性,并正常運行一個密碼審計腳本。
(2)數(shù)據(jù)庫角色的管理
確保需要使用Web 應用的SQL 用戶具有最低訪問權限。
(3))檢查服務器的補丁狀況
針對SQL-Server 的漏洞,及時升級安全補丁。
(4)檢驗IIS 日志和數(shù)據(jù)表。
本文對SQL 注入攻擊的原理、常用注入過程和后果進行了描述和總結,并著重闡述了通過字符串過濾、使用正則表達式、預編譯方法和SQL Server 防御來構建防范SQL注入的思路和方法,并給出了相應代碼。本文對于越來越多的Web 動態(tài)應用程序提供了較好的防范SQL 注入式攻擊的解決方案,具有一定的現(xiàn)實意義。
[1]秦浩.淺析常見的 Web服務攻擊[J].自動化與儀器儀表,2009,(3).
[2]賽門鐵克第 2 期.Symantec 資訊[EB/OL].http://www.cww.net.cn/zhuanti/html/2009/2/10/200921095084992.htm.
[3]Anley C.Advanced SQL injection in SQL server Applications[EB/OL].http://www.creangel.com/papers/adva nced_sql_injection.pdf, An NGSSoftware Insight Security Research (NISR)Publication,2002.
[4]郭立川.SQL 注入思路與防注入辦法[J].軟件導論,2010,(3).
[5]王云,郭外萍,陳承歡.Web 項目中的SQL 注入問題研究與防范方法[J].計算機工程與設計,2010,31(5).
TP393.08
A
1008-1151(2011)04-0048-02
2011-01-11
北京市教委科技發(fā)展計劃基金項目(KM200810772010);2010年度科研水平提高項目資助(資助號:5028123400
岳清(1973-),女,河南鄭州人,北京信息科技大學計算機學院講師,碩士,從事數(shù)據(jù)庫安全、軟件工程等研究。