陳學(xué)平
CHEN Xue-ping
(重慶電子工程職業(yè)學(xué)院 技師學(xué)院,重慶 401331)
網(wǎng)站數(shù)據(jù)庫SQL注入及防范
Web database and preventing SQL injection
陳學(xué)平
CHEN Xue-ping
(重慶電子工程職業(yè)學(xué)院 技師學(xué)院,重慶 401331)
SQL注入是一種入侵WEB服務(wù)器的方法.當(dāng)網(wǎng)站應(yīng)用程序?qū)邮盏降臄?shù)據(jù)沒進(jìn)行嚴(yán)格過濾時,它便有可能存在SQL注入漏洞.文中將介紹入侵者利用SQL注入方法入侵WEB服務(wù)器的思路,并且給出相應(yīng)的防御方法。通過在實際項目中的使用,能夠很好的進(jìn)行主動防范,具有較高的實用價值。
數(shù)據(jù)庫安全;SQL注入;SQL防范
對于采用“虛擬主機(jī)”的方式建立的中小型網(wǎng)站,其后臺數(shù)據(jù)庫絕大多數(shù)采用Access數(shù)據(jù)庫。如果有人通過各種方法獲得或者猜到數(shù)據(jù)庫的存儲路徑和文件名,則該數(shù)據(jù)庫可以被下載到本地。
為了防止被非法下載和訪問,可采取以下措施:
1)改變數(shù)據(jù)庫名稱。為數(shù)據(jù)庫文件起個復(fù)雜的非常規(guī)的名字,并放在幾層目錄下。所謂“非常規(guī)”,就是說如果有個數(shù)據(jù)庫要保存的是有關(guān)電子商店的信息,不把它命名為“eshop.mdb”,而是起個比較怪的名稱,如d34ksfslf.mdb,再放在如/kdslf/i44/studi/ 的幾層目錄下,這樣黑客要想通過猜的方式得到Access數(shù)據(jù)庫文件就比較困難了。
2)不把數(shù)據(jù)庫名寫在程序中。許多人都把DSN寫在程序中,比如DBPath= Server.MapPath("cmddb.mdb")conn.Open "driver={Microsoft Access Driver (*.mdb)};dbq=" & DBPath 假如萬一給人拿到了源程序,Access數(shù)據(jù)庫的名字就一覽無余。因此建議在ODBC里設(shè)置數(shù)據(jù)源,再在程序中這樣寫:conn.open "shujiyuan"。
3)改變數(shù)據(jù)庫文件的擴(kuò)展名。如把a(bǔ)bc134.mdb改為abc134.asp,這樣在ASP文件及數(shù)據(jù)庫操作中仍然可以正常使用。但在非法訪問者看來,該文件已不是數(shù)據(jù)庫文件了。
4)加密Access數(shù)據(jù)庫文件。選取"工具→安全→加密/解密數(shù)據(jù)庫,選取數(shù)據(jù)庫(如employer.mdb),然后按“確定”按鈕,會出現(xiàn)"數(shù)據(jù)庫加密后另存為"的窗口,存為employer1.mdb。接著,employer.mdb會被編碼,然后存為employer1.mdb。要注意的是,以上的方法并不是對數(shù)據(jù)庫設(shè)置密碼,而只是對數(shù)據(jù)庫文件內(nèi)容加密,目的是為了防止他人使用別的工具來查看數(shù)據(jù)庫文件的內(nèi)容。接下來為數(shù)據(jù)庫設(shè)置密碼,首先打開經(jīng)過編碼的employer1.mdb,在打開時,選擇"獨占"方式。然后選取功能表的"工具→安全→設(shè)置數(shù)據(jù)庫密碼",輸入密碼即可。為employer1.mdb設(shè)置密碼之后,如果再使用Access數(shù)據(jù)庫文件時,則Access會先要求輸入密碼,驗證正確后才能夠啟動數(shù)據(jù)庫,可以在ASP程序中的connection對象的open方法中增加PWD的參數(shù)來訪問有密碼保護(hù)的數(shù)據(jù)庫文件,
例如:
param="driver={Microsoft AccessDriver(*.md b)};Pwd=yfdsfs"param=param&";
dbq="&server.mappath("employer1.mdb")conn.open param
這樣即使別人得到了employer1.mdb文件,沒有密碼是無法看到employer1.mdb的內(nèi)容。
綜合使用上述方法,數(shù)據(jù)庫被非法下載的可能性就會降低。
許多動態(tài)網(wǎng)站在編寫程序時,沒有對用戶輸入數(shù)據(jù)的合法性進(jìn)行判斷,使應(yīng)用程序存在安全隱患。用戶通過向數(shù)據(jù)庫提交一段精心構(gòu)造的SQL查詢代碼,(一般是在瀏覽器地址欄進(jìn)行,通過正常的www端口訪問)根據(jù)程序返回的結(jié)果,收集網(wǎng)站與數(shù)據(jù)庫的信息,進(jìn)而非法獲得網(wǎng)站數(shù)據(jù)庫中的敏感信息或向其中添加自定義數(shù)據(jù),這就是SQL Injection,即SQL注入攻擊。SQL注入攻擊使用簡單,危害大。被攻擊成功的網(wǎng)站往往被攻擊者掌握最高權(quán)限,可任意增刪數(shù)據(jù)。
為了說明SQL注入攻擊的原理,可在本地網(wǎng)站上http://localhost/進(jìn)行測試。
http://localhost/show.asp?ID=123是一個正常的網(wǎng)頁地址,將這個網(wǎng)址提交到服務(wù)器后,服務(wù)器將進(jìn)行類似Select * from 表名 where 字段="&ID的查詢(ID即客戶端提交的參數(shù),本例是即123),再將查詢結(jié)果返回給客戶端,如果在這個地址后面加上單引號’,服務(wù)器會返回下面的錯誤提示:
Microsoft JET Database Engine 錯誤 '80040e14'
字符串的語法錯誤 在查詢表達(dá)式 'ID=123'' 中。
/show.asp,行8
從這個錯誤提示我們能看出下面幾點:
1)網(wǎng)站使用的是Access數(shù)據(jù)庫,通過JET引擎連接數(shù)據(jù)庫,而不是通過ODBC。
2)程序沒有判斷客戶端提交的數(shù)據(jù)是否符合程序要求。
3)該SQL語句所查詢的表中有一名為ID的字段。
除了上述介紹的在頁面地址欄中加單引號“’”的方法判斷可否注入外,還可以在頁面地址后面分別加入“and 1=1 ”和“and 1=2”來測試網(wǎng)站能否注入,這就是經(jīng)典的1=1、1=2測試法,通過其返回結(jié)果判斷能否注入:
1)http://localhost/show.asp?id=123
2)http://localhost/show.asp?id=123 and 1=1
3)http://localhost/show.asp?id=123 and 1=2
可以注入的表現(xiàn):
1)正常顯示(這是必然的,不然就是程序有錯誤了)
2)正常顯示,內(nèi)容基本與①相同
3)提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內(nèi)容為空(程序加了on error resume next)
不可以注入就比較容易判斷了,1)同樣正常顯示,2)和3)一般都會有程序定義的錯誤提示,或提示類型轉(zhuǎn)換時出錯。
不同的數(shù)據(jù)庫的函數(shù)、注入方法都是有差異的,通常在注入之前,攻擊者還要判斷一下數(shù)據(jù)庫的類型。一般ASP最常搭配的數(shù)據(jù)庫是Access和SQLServer。
SQLServer有一些系統(tǒng)變量,如果服務(wù)器IIS提示沒關(guān)閉,并且SQLServer返回錯誤提示的話,那可以直接從出錯信息獲取,方法如下:
http://localhost/show.asp?id=123 and user>0
這句語句的前面的部分是正常的,重點在and user>0,我們知道,user是SQLServer的一個內(nèi)置變量,它的值是當(dāng)前連接的用戶名,類型為nvarchar。拿一個nvarchar的值跟int的數(shù)0比較,系統(tǒng)會先試圖將nvarchar的值轉(zhuǎn)成int型,當(dāng)然,轉(zhuǎn)的過程中肯定會出錯,SQLServer的出錯提示類似于:將nvarchar值 ”abc” 轉(zhuǎn)換數(shù)據(jù)類型為 int的列時發(fā)生語法錯誤,其中,abc正是變量user的值,這樣,很容易就得到了數(shù)據(jù)庫的用戶名。
如果服務(wù)器IIS不允許返回錯誤提示,那怎么判斷數(shù)據(jù)庫類型呢?攻擊者可以從Access和SQLServer和區(qū)別入手,Access和SQLServer都有自己的系統(tǒng)表,比如存放數(shù)據(jù)庫中所有對象的表,Access是在系統(tǒng)表[msysobjects]中,但在Web環(huán)境下讀該表會提示“沒有權(quán)限”,SQLServer是在表[sysobjects]中,在Web環(huán)境下可正常讀取。
在確認(rèn)可以注入的情況下,使用下面的語句:
http://localhost/show.asp?id=123? and (select count(*) from sysobjects)>0
http://localhost/show.asp?id=123? and (select count(*) from msysobjects)>0
如果數(shù)據(jù)庫是SQLServer,那么第一個網(wǎng)址的頁面與原頁面http://localhost/show.asp?id=123是大致相同的;而第二個網(wǎng)址,由于找不到表msysobjects,會提示出錯,就算程序有容錯處理,頁面也與原頁面完全不同。
如果數(shù)據(jù)庫用的是Access,那么情況就有所不同,第一個網(wǎng)址的頁面與原頁面完全不同;第二個網(wǎng)址,則視乎數(shù)據(jù)庫設(shè)置是否允許讀該系統(tǒng)表,一般來說是不允許的,所以與原網(wǎng)址也是完全不同。大多數(shù)情況下,用第一個網(wǎng)址就可以得知系統(tǒng)所用的數(shù)據(jù)庫類型,第二個網(wǎng)址只作為開啟IIS錯誤提示時的驗證。
對于存在著SQL注入攻擊漏洞的網(wǎng)站,攻擊者可以通過專用工具或手工構(gòu)造特殊代碼不斷猜測嘗試,獲得數(shù)據(jù)庫名、表名、表中的字段名稱,甚至是具有系統(tǒng)管理權(quán)限的用戶帳號和密碼、上傳病毒、木馬或惡意文件,給網(wǎng)站帶來巨大危害。下面講述如何防止SQL注入。
1)設(shè)置ASP錯誤提示
SQL注入入侵是根據(jù)IIS給出的ASP錯誤提示信息來入侵的,如果把IIS設(shè)置成不管出什么樣的ASP錯誤,只給出一種錯誤提示信息,即http 500錯誤,那么攻擊者就沒辦法直接得到網(wǎng)站的數(shù)據(jù)庫信息,也就很難確定下一步的攻擊目標(biāo)了。具體設(shè)置參見圖1。主要把500:100這個錯誤的默認(rèn)提示頁面 C:WINDOWSHelpiisHelpcommon500-100.asp改成自定義的C:WINDOWSHelpiisHelpcommon500.htm即可,這時,無論ASP運行中出什么錯,服務(wù)器都只提示HTTP 500錯誤。
圖1 IIS出錯信息設(shè)置
但是這樣設(shè)置一個不好的地方是程序員編寫的代碼出錯時,服務(wù)器不給出詳細(xì)的錯誤提示信息,會給程序調(diào)試帶來很大的不便。不過,服務(wù)器畢竟不是測試代碼的地方,應(yīng)堅持安全穩(wěn)定第一,這樣設(shè)置也是無可厚非的,事實上許多服務(wù)器的出錯信息都是如此設(shè)置。
2)過濾敏感字符
在程序中對客戶端提交的數(shù)據(jù)進(jìn)行檢查,如果輸入中存在著特殊字符(如’、<、>、=等),或者輸入的字符中含有SQL語言中的命令動詞(如insert、select、update等),就認(rèn)為是SQL注入式攻擊,系統(tǒng)立即停止執(zhí)行并給出警告信息或者轉(zhuǎn)向出錯頁面。
下面是防止注入式攻擊的asp代碼,使用時加入到相應(yīng)的asp文件中即可。該代碼并沒有實際記錄攻擊者的相關(guān)信息,只是嚇唬而已,如有必有,完全可以把攻擊者的數(shù)據(jù)記錄到特定的文件中,以備查看。
常見的是利用MD5進(jìn)行加密處理,用MD5加密的數(shù)據(jù)不能被反向解密,即使看見了加密后的密文也不能得到原始數(shù)據(jù)。使用時,把用VBScript實現(xiàn)MD5算法的文件md5.asp包含在文件中,然后用md5(user_password)的形式調(diào)用,即可得到加密后的密文。如:
由于篇幅所限,上述md5.asp文件省略。
我們上面介紹了網(wǎng)站數(shù)據(jù)庫的SQL注入防范方法,我們平常在網(wǎng)站制作完成后,可用NBSI、HDSI、DFomain、《啊D注入工具》等網(wǎng)頁注入工具對網(wǎng)站進(jìn)行檢測,如果不能被注入,才可以正式發(fā)布運行。
[1] 沈昌樣.網(wǎng)絡(luò)安全與信息戰(zhàn).網(wǎng)絡(luò)安全技術(shù)與應(yīng)用.2001.
[2] 陳學(xué)平,余永洪.中小型網(wǎng)站建設(shè)與管理.第二版,2009.
TH166
A
1009-0134(2010)10(上)-0192-04
10.3969/j.issn.1009-0134.2010.10(上).60
2009-12-28
陳學(xué)平(1967 -),男,副教授,研究方向為電子、通信、計算機(jī)網(wǎng)絡(luò)等。