孟慶君 杜瑞慶
摘 要:現(xiàn)今網(wǎng)站上的數(shù)據(jù)庫大多使用SQL Server數(shù)據(jù)庫,對數(shù)據(jù)庫進入訪問時一般需要輸入賬戶和密碼進行登錄,但是SQL存在的注入漏洞可以使任意賬戶順利登錄,文章探討了常見的SQL注入萬能密碼能夠成功登錄的原因,并提出了使用參數(shù)化查詢解決這種問題的方法。參數(shù)化查詢首先編譯SQL語句,僅將參數(shù)進行編譯,其后緊隨的恒為真的條件語句將被截取掉,因此實現(xiàn)對注入漏洞的防范。
關(guān)鍵詞:ASP.NET SQL注入漏洞 登錄 參數(shù)化查詢
中圖分類號:TP393 文獻標識碼:A 文章編號:1672-3791(2018)06(c)-0007-02
在網(wǎng)絡(luò)日益盛行的今天,通過網(wǎng)絡(luò)可以進行各種各樣的操作,包括生活中的各種與財務(wù)相關(guān)操作,比如:轉(zhuǎn)賬操作以及手機話費、水電費、煤氣費與暖氣費的繳納。在進行財務(wù)操作之前,需要進行用戶登錄操作,即要求用戶首先輸入賬號和密碼,在服務(wù)器上驗證通過才可進行后面的操作。通過賬號與密碼的驗證可保障用戶信息的安全,尤其是財務(wù)信息安全。
1 SQL注入漏洞
這些賬號和密碼大都保存在服務(wù)器上的數(shù)據(jù)庫文件中,大部分網(wǎng)站使用的數(shù)據(jù)庫是微軟出品的SQL Server數(shù)據(jù)庫。這種數(shù)據(jù)庫功能強大,使用方便,但在安全性上也有一定的漏洞。比如:常見的SQL注入漏洞,它使得用戶可能通過輸入一些特殊的密碼就能夠以假亂真,正常登錄,并進行登錄后的財務(wù)操作,從而造成用戶的賬務(wù)損失。表1列出了一些常見的SQL注入萬能密碼。
網(wǎng)站上的用戶登錄網(wǎng)頁往往以圖1形式存在,要求用戶在文本框中輸入用戶名和密碼,然后點擊“登錄”按鈕進行驗證。許多這樣的網(wǎng)頁是由ASP.NET(C#)開發(fā)的,點擊“登錄”按鈕時,會將文本框中的用戶名與密碼取出來與SQL Server數(shù)據(jù)庫中的已經(jīng)存儲的用戶信息進行比對,成功則進入下一步操作;如果數(shù)據(jù)庫中沒有相應(yīng)用戶信息,或者有用戶的賬號,但密碼不正確,都不能通過驗證,也不能進入下一步的操作。但SQL Server的注入漏洞,使一些萬能密碼可以騙過網(wǎng)頁的驗證程序。原因如下。
首先要分析一下用戶登錄頁面的代碼,就能找到原因。點擊“登錄”按鈕的關(guān)鍵代碼如下。
string strUserName = txtUser.Text;
string strUserPwd = txtPwd.Text;
……
com.CommandText = "select * from userInfo where userName='"+strUserName+"'and userPwd='"+strUserPwd+"'";
從代碼中可以看到,首先獲取文本框中的賬號和密碼,然后用查詢語句來驗證用戶名與密碼是否都正確。如果輸入的用戶名為“user123”,密碼為“123123”,則查詢語句會變?yōu)椤皊elect * from userInfo where userName='user123' and userPwd='123123' ”,這時從數(shù)據(jù)庫中如果能夠查找到賬號與密碼都正確的信息才能夠通過登錄驗證,如果其中有一個不正確,則不能通過驗證。SQL注入萬能密碼利用了這個查詢語句中的邏輯表達式的漏洞,給它加上一個絕對為真的條件,達到以假亂真、輸入任意賬戶名均可登錄的目的。那么,它是如何做到的?
例如:在網(wǎng)頁顯示的賬號文本框中隨便輸入一個用戶名“aaa”,再在密碼文本框中輸入一個萬能密碼“' or 'a'='a”,則查詢語句會變?yōu)椤皊elect * from userInfo where userName='aaa' and userPwd='' or 'a'='a'”??梢钥吹狡渲械倪壿嫳磉_式中有一個“'a'='a'”恒為真的條件,因此不管用戶名“aaa”在數(shù)據(jù)庫中是否存在,其對應(yīng)的密碼是否存在,這個查詢語句中的邏輯表達式恒為真,查詢就相當(dāng)于“select * from userInfo where 1”,因此可以登錄成功。
2 SQL注入漏洞的預(yù)防
以前對付這種漏洞的方式主要有3種。
(1)字符串檢測。限定輸入的內(nèi)容只能由英文、數(shù)字等常規(guī)字符,如果檢查到用戶輸入有特殊字符,直接拒絕。缺點是,系統(tǒng)中不可避免地會有些內(nèi)容包含特殊字符,這時候總不能拒絕入庫。
(2)字符串替換。把危險字符替換成其他字符,缺點是危險字符可能有很多,一一枚舉替換相當(dāng)麻煩,也可能有漏網(wǎng)之魚。
(3)存儲過程。把參數(shù)傳到存儲過程進行處理,但并不是所有數(shù)據(jù)庫都支持存儲過程。如果存儲過程中執(zhí)行的命令也是通過拼接字符串出來的,還是會有漏洞。
近年來,自從參數(shù)化查詢出現(xiàn)后,SQL注入漏洞基本杜絕。
3 參數(shù)化查詢
參數(shù)化查詢(Parameterized Query 或 Parameterized Statement)是訪問數(shù)據(jù)庫時,在需要填入數(shù)值或數(shù)據(jù)的地方,使用參數(shù)(Parameter)來給值。在使用參數(shù)化查詢的情況下,數(shù)據(jù)庫服務(wù)器不會將參數(shù)的內(nèi)容視為SQL指令的一部份來處理,而是在數(shù)據(jù)庫完成SQL指令的編譯后,才套用參數(shù)運行,因此就算參數(shù)中含有指令,也不會被數(shù)據(jù)庫運行。Access、SQL Server、MySQL、SQLite等常用數(shù)據(jù)庫都支持參數(shù)化查詢。
ASP.NET(C#)創(chuàng)建的網(wǎng)頁中,也可利用參數(shù)化查詢的方法對注入漏洞進行防范。將上述的代碼加上參數(shù)化查詢的語句即可,如下所示:
com.CommandText = "select * from userInfo where userName=@user and userPwd=@pwd”;
com.Parameters.Add("@user",System.Data.SqlDbType.VarChar,20).Value=txtUser.Text.Trim();
com.Parameters.Add("@pwd",System.Data.SqlDbType.VarChar,20).Value=txtPwd.Text.Trim();
從代碼中可以看到為sqlCommand對象com增加了兩個參數(shù),分別命名為“@user”與“@pwd”,并將賬戶號與密碼作為參數(shù)值傳給這兩個參數(shù),在進行數(shù)據(jù)庫查詢時,數(shù)據(jù)庫首先要將查詢語句進行編譯。在編譯時,僅常量參與編譯,因此就無法追加恒為真的后門命令。上面談到的例子中,查詢語句“select * from userInfo where userName='aaa' and userPwd='' or 'a'='a'”在編譯時會截取為“select * from userInfo where userName='aaa' and userPwd=''”,后面恒為真的條件就不存在了,因此就防范了注入漏洞。
4 結(jié)語
參數(shù)化查詢是防范SQL注入漏洞的一種方法,它首先編譯SQL語句,僅將參數(shù)進行編譯,其后緊隨的恒為真的條件語句將被截取掉,因此實現(xiàn)對注入漏洞的防范。
參考文獻
[1] 張瑩瑩,凌捷.一種SQL注入漏洞定位檢測方法[J].計算機應(yīng)用與軟件,2016,33(2):314-317.
[2] 練坤梅,許靜,田偉,等.SQL注入漏洞多等級檢測方法研究[J].計算機科學(xué)與探索,2011,5(5):474-480.
[3] 馬小婷,胡國平,李舟軍.SQL注入漏洞檢測與防御技術(shù)研究[J].計算機安全,2010(11):18-24.
[4] 彭賡,范明鈺.基于改進網(wǎng)絡(luò)爬蟲技術(shù)的SQL注入漏洞檢測[J].計算機應(yīng)用研究,2010,27(7):2605-2607.
[5] 朱輝,沈明星,李善平.Web應(yīng)用中代碼注入漏洞的測試方法[J].計算機工程,2010,36(10):173-175,178.
[6] 張濤,王行建.對SQL注入漏洞的研究與防范措施的探討[J].計算機時代,2006(11):30-31,38.
[7] 顧坤鵬,宋順林.基于C++的關(guān)系代數(shù)產(chǎn)生的安全SQL查詢[J].計算機與現(xiàn)代化,2011(10):177-180.