楊 義 楊玉龍 張?zhí)烊?李 帥
(貴州航天計(jì)量測(cè)試技術(shù)研究所,貴州 貴陽(yáng) 550009)
B/S(Browser/Server)網(wǎng)絡(luò)架構(gòu)的出現(xiàn),使得用戶只需要一臺(tái)能上網(wǎng)的電腦,就可以方便地在任何地方進(jìn)行操作而不用安裝任何專門(mén)的軟件,但是隨之而來(lái)的安全問(wèn)題不斷出現(xiàn)。最常見(jiàn)的就是SQL注入攻擊,之所以SQL注入攻擊如此常見(jiàn),是因?yàn)樗恍枰粽哂泻苌钊氲木幊坦Φ?,只要能熟練使用SQL語(yǔ)言即可。SQL注入可以導(dǎo)致數(shù)據(jù)庫(kù)系統(tǒng)中的普通用戶竊取機(jī)密數(shù)據(jù)、進(jìn)行權(quán)限提升等,具有很強(qiáng)的破壞性。
結(jié)構(gòu)化查詢語(yǔ)言(Structured Query Language)簡(jiǎn)稱SQL,是一種用來(lái)和數(shù)據(jù)庫(kù)交互的腳本語(yǔ)言,現(xiàn)今幾大主流數(shù)據(jù)庫(kù)都使用SQL語(yǔ)言。目前易受到SQL注入攻擊的兩大系統(tǒng)平臺(tái)組合是:SQL Server+ASP和MySQL+PHP,SQL Server和MySQL作為關(guān)系型數(shù)據(jù)庫(kù),均采用SQL語(yǔ)言;ASP與PHP作為服務(wù)器端腳本語(yǔ)言,服務(wù)器端腳本程序是存在漏洞的,SQL注入攻擊就是因此而存在的。而使用SQL Server+.NET系統(tǒng)平臺(tái)組合相對(duì)安全些,因?yàn)?NET Framework開(kāi)發(fā)提供了一系列的安全措施,如:.NET加密技術(shù),.NET的基于角色的安全技術(shù)。
SQL注入問(wèn)題受到開(kāi)發(fā)者的廣泛關(guān)注,2011年朱輝等提出了使用存儲(chǔ)過(guò)程的方法可有效防止SQL注入攻擊,但是沒(méi)給出存儲(chǔ)過(guò)程如何防止SQL注入的具體分析[3]。本文具體分析了存儲(chǔ)過(guò)程可有效解決SQL注入問(wèn)題,并指出其本質(zhì)。同時(shí)提出了幾點(diǎn).NET開(kāi)發(fā)中的安全措施,可以很大程度上增強(qiáng)系統(tǒng)的安全性。
2002年,Chris Anley將SQL注入定義為:攻擊者通過(guò)在查詢操作中插入一系列的SQL語(yǔ)句到應(yīng)用程序中來(lái)操作數(shù)據(jù)。SQL注入攻擊的基本思想:通過(guò)向用戶輸入的信息中注入一些額外的特殊字符或者SQL語(yǔ)句,使系統(tǒng)服務(wù)器端構(gòu)造出來(lái)的SQL語(yǔ)句在執(zhí)行時(shí)改變了查詢條件,或者附帶執(zhí)行了攻擊者想要執(zhí)行的SQL語(yǔ)句。由此,攻擊者獲得數(shù)據(jù)庫(kù)的操作權(quán)限,或者根據(jù)程序返回的結(jié)果,獲得一些想知道的數(shù)據(jù)。
SQL注入主要是從SQL的語(yǔ)法中基于數(shù)據(jù)的應(yīng)用程序存在的漏洞而存在的,因此而導(dǎo)致SQL注入攻擊具有廣泛性。理論上說(shuō),SQL注入攻擊對(duì)于所有基于SQL語(yǔ)言標(biāo)準(zhǔn)的數(shù)據(jù)庫(kù)軟件都是有效的。下面給出一個(gè)簡(jiǎn)單的SQL注入攻擊示例:
我們?cè)诮?jīng)常使用某個(gè)系統(tǒng)或需要登錄網(wǎng)站時(shí),會(huì)通過(guò)表單的方式,提交自己的用戶名(username)和密碼(password),這時(shí)用戶名和密碼會(huì)被傳遞到Web服務(wù)器,在Web服務(wù)器端會(huì)進(jìn)行有關(guān)SQL語(yǔ)句的重構(gòu),然后將重構(gòu)的SQL傳遞給數(shù)據(jù)庫(kù)服務(wù)器,在服務(wù)器端對(duì)SQL語(yǔ)句進(jìn)行解析,返回查詢結(jié)果,以此來(lái)判斷是否允許登錄。
一般在Web服務(wù)器端構(gòu)造如下SQL查詢語(yǔ)句:
select count(0)from user where username='"+username+"'and password='"+password+"'
假設(shè)數(shù)據(jù)庫(kù)中存在用戶“admin,123”,即用戶名username為admin,密碼password為123,系統(tǒng)會(huì)對(duì)用戶名進(jìn)行查詢,判斷是否存在該用戶名的用戶。但是,對(duì)于惡意攻擊者來(lái)說(shuō)不會(huì)這么輸入,由于惡意攻擊者不知道用戶名和密碼,通常會(huì)提交惡意數(shù)據(jù),如:username=admin,password='321'or'1'='1'使得服務(wù)器構(gòu)造的SQL查詢語(yǔ)句變成select count(0)from admin where username='admin'and password='321'or'1'='1'。
因?yàn)?1'='1'恒為真,攻擊者就可以繞過(guò)對(duì)密碼的驗(yàn)證,只驗(yàn)證用戶名,圖1是SQL注入攻擊的實(shí)例圖。
圖1 SQL注入攻擊
圖中顯示了一般情況下的SQL注入攻擊過(guò)程。為了獲取更多的數(shù)據(jù)信息,攻擊者會(huì)通過(guò)SQL的深層次注入攻擊,在攻擊中在數(shù)據(jù)庫(kù)中添加自己的賬戶。
對(duì)于.NET開(kāi)發(fā)初學(xué)者來(lái)說(shuō),很多人還停留在直接使用SQL語(yǔ)句訪問(wèn)數(shù)據(jù)庫(kù)或者對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行修改。這就給善于SQL注入攻擊的攻擊者帶來(lái)了機(jī)會(huì),目前對(duì)于SQL注入攻擊的研究已比較深入。一般的SQL注入攻擊防范方法總結(jié)如下:
2.2.1 WEB服務(wù)器的安全配置
(1)修改或者去掉WEB服務(wù)器上默認(rèn)的一些危險(xiǎn)命令,例如服務(wù)器安裝之后的一些默認(rèn)用戶名和賬戶;
(2)屏蔽一些出錯(cuò)信息;
(3)配置目錄的權(quán)限,分情況設(shè)置訪問(wèn)目錄的權(quán)限,盡量不給寫(xiě)目錄權(quán)限。
2.2.2 數(shù)據(jù)庫(kù)的安全配置
(1)修改數(shù)據(jù)庫(kù)的初始設(shè)置,修改或者去掉數(shù)據(jù)庫(kù)系統(tǒng)安裝之后產(chǎn)生的默認(rèn)登錄賬戶;
(2)及時(shí)升級(jí)數(shù)據(jù)庫(kù);
(3)限定WEB應(yīng)用程序連接數(shù)據(jù)庫(kù)的用戶權(quán)限。
2.2.3 過(guò)濾特殊字符
(1)替換或刪除敏感字符、字符串;
(2)使用變量代替字串,建立SQL查詢,因?yàn)樽兞坎皇强梢詧?zhí)行的腳本。
除了以上基本的防范措施,在系統(tǒng)開(kāi)發(fā)中,使用存儲(chǔ)過(guò)程來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的查詢、刪除、更新等操作將是更有效的防止SQL注入攻擊方法。
存儲(chǔ)過(guò)程是建立在數(shù)據(jù)庫(kù)服務(wù)器端的SQL語(yǔ)句與部分控制流語(yǔ)句的預(yù)編譯集合,通過(guò)將某些關(guān)于數(shù)據(jù)庫(kù)操作的語(yǔ)言集中,交給SQL數(shù)據(jù)庫(kù)服務(wù)器來(lái)完成特定的任務(wù)。
存儲(chǔ)過(guò)程能有效提高系統(tǒng)的性能,主要是因?yàn)榇鎯?chǔ)過(guò)程在經(jīng)過(guò)第一次執(zhí)行后,會(huì)把查詢計(jì)劃保留在內(nèi)存中,以后在調(diào)用時(shí),就無(wú)須進(jìn)行編譯,直接調(diào)用該存儲(chǔ)過(guò)程。存儲(chǔ)過(guò)程具有以下三個(gè)方面的優(yōu)點(diǎn):
(1)通過(guò)本地存儲(chǔ)、代碼預(yù)編譯和緩存技術(shù)實(shí)現(xiàn)高性能的數(shù)據(jù)操作;
(2)通過(guò)通用編程結(jié)構(gòu)和過(guò)程重用實(shí)現(xiàn)編程框架;
(3)通過(guò)隔離和加密的方法提高了數(shù)據(jù)庫(kù)的安全性。
存儲(chǔ)過(guò)程如何防止SQL注入攻擊,以身份驗(yàn)證為例:
create procedure sp_getAdmin
(@adminName varchar(20),
@adminPwd varchar(50))
as
select count(0)from admin where adminName=@admin-Name and adminPwd=@adminPwd
go
在這個(gè)存儲(chǔ)過(guò)程中可以看到有兩個(gè)輸入?yún)?shù)@admin-Name和@adminPwd,數(shù)據(jù)類型都為varchar,這里應(yīng)用SQL注入攻擊中常用的方法,在登錄驗(yàn)證中提交adminName為admin'--,adminPwd為123。如果不用存儲(chǔ)過(guò)程,驗(yàn)證語(yǔ)句為:select count(0)from admin where adminName='admin'--'and adminPwd='123',這時(shí)密碼adminPwd參數(shù)因?yàn)椤?-”被解釋為注釋語(yǔ)句,從而在數(shù)據(jù)庫(kù)服務(wù)器端就只對(duì)用戶名進(jìn)行驗(yàn)證,而不對(duì)密碼進(jìn)行驗(yàn)證。
上面@adminName與@adminPwd為存儲(chǔ)過(guò)程參數(shù),主要用于在存儲(chǔ)過(guò)程和調(diào)用存儲(chǔ)過(guò)程的應(yīng)用程序或者工具之間傳輸數(shù)據(jù)。輸入?yún)?shù)用于調(diào)用方法的數(shù)據(jù)值傳遞到存儲(chǔ)過(guò)程,輸出參數(shù)用于存儲(chǔ)過(guò)程將數(shù)值或游標(biāo)變量傳遞回調(diào)用方,它們被預(yù)先作為獨(dú)立的數(shù)據(jù)體與SQL語(yǔ)句交互。
在上述sp_getAdmin存儲(chǔ)過(guò)程中,輸入?yún)?shù)@admin-Name和@adminPwd被當(dāng)成兩個(gè)獨(dú)立的數(shù)據(jù)體和SQL語(yǔ)句交互,而不是與一般的SQL語(yǔ)句一樣,將傳進(jìn)的參數(shù)與SQL語(yǔ)句重組。驗(yàn)證過(guò)程中,admin'--作為一個(gè)字符串傳遞給參數(shù)@username,123也作為一個(gè)字符串傳遞給參數(shù)@password。存儲(chǔ)過(guò)程中的SQL查詢語(yǔ)句不會(huì)重新組合為:select count(0)from admin where adminName='admin'--'and admin-Pwd='123',也就是“--”不會(huì)將后面的SQL語(yǔ)句注釋掉,“ad-min'--”是一個(gè)整體。
因此存儲(chǔ)過(guò)程驗(yàn)證用戶名和密碼,是有效的身份驗(yàn)證方法,在高效率訪問(wèn)數(shù)據(jù)庫(kù)的同時(shí),解決了SQL Injection攻擊。但是使用了存儲(chǔ)過(guò)程實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作之后,并不等于SQL注入攻擊從此不會(huì)再出現(xiàn)。要使SQL注入攻擊成為不可能,最終取決于服務(wù)器端調(diào)用存儲(chǔ)過(guò)程的方式。針對(duì)不同的安全級(jí)別需求,還可以使用EXECUTE AS子句設(shè)定存儲(chǔ)過(guò)程的安全上下文。
跨站腳本攻擊(Cross Site Script Execution,XSS)指攻擊者利用網(wǎng)頁(yè)漏洞向客戶端注入腳本代碼,然后這些代碼被發(fā)送到受信任的客戶端上并被瀏覽器解釋執(zhí)行,攻擊者利用這些代碼盜取用戶資料或利用用戶身份對(duì)訪問(wèn)者進(jìn)行病毒侵害。代碼本身多用HTML和JavaScript編寫(xiě),但也可能擴(kuò)展到VBScript、ActiveX,或其它瀏覽器支持的技術(shù)。根據(jù)形成原因的不同,跨站腳本攻擊可以分為三種攻擊類型,分別是反射型XSS攻擊、存儲(chǔ)型XSS攻擊和DOM型XSS攻擊[5]。
為有效防止跨站腳本攻擊,微軟在ASP.NET 1.1之后的版本中都引入了對(duì)提交表單自動(dòng)檢測(cè)是否存在XSS的能力,但是很多程序員沒(méi)意識(shí)到。當(dāng)程序出現(xiàn)類似于HttpRequest-ValidationException或者“A potentially dangerous Request.Form value was detected from the client”的時(shí)候,很多程序員通過(guò)在ASP.NET頁(yè)面的page中或者web.config配置文件中設(shè)置validateRequest=false來(lái)禁用這個(gè)特性,以達(dá)到解決問(wèn)題的目的。但是這樣做會(huì)使得ASP.NET的自動(dòng)檢測(cè)XSS功能失效,失去了安全保護(hù)措施。在.NET開(kāi)發(fā)中,每一個(gè)標(biāo)記的屬性都有其特有的用處,在不了解的情況下,不要輕易修改。
使用存儲(chǔ)過(guò)程加密技術(shù),使得非系統(tǒng)維護(hù)者,無(wú)法修改數(shù)據(jù)庫(kù)服務(wù)器中的存儲(chǔ)過(guò)程。對(duì)于一般的企業(yè),其數(shù)據(jù)庫(kù)服務(wù)器是托管的或租用的,這樣存在一個(gè)安全隱患,如果非法用戶通過(guò)其他手段登上了其SQL Server服務(wù)器,或通過(guò)注入得到了存儲(chǔ)過(guò)程,然后將存儲(chǔ)過(guò)程中的業(yè)務(wù)邏輯等修改,如果在此前數(shù)據(jù)庫(kù)未做備份那將造成不可估量的損失。對(duì)存儲(chǔ)過(guò)程加密的示例:
create procedure sp_getAdmin
(@adminName varchar(20),
@adminPwd varchar(50))with encryption
as
select count(0)from admin where adminName=@admin-Name and adminPwd=@adminPwd
go
需要注意的是,應(yīng)先備份原始的存儲(chǔ)過(guò)程,再進(jìn)行加密,同時(shí)在生產(chǎn)環(huán)境前需完成加密。
系統(tǒng)管理員密碼加密是指在進(jìn)行密碼比對(duì)時(shí),會(huì)通過(guò)把用戶輸入的密碼與數(shù)據(jù)庫(kù)中事先加密好的系統(tǒng)管理員密碼進(jìn)行比較,從而驗(yàn)證用戶是否合法。下面就是ASP.NET中常用的兩種Hash算法MD5和SHA1相關(guān)類[6]:
MD5相關(guān)類:
System.Security.Cryptography.MD5
System.Security.Cryptography.MD5CryptoServiceProvider()
System.Web.Security.FormsAuthentication.HashPassword-ForStoringInConfigFile(strSource,"MD5")
SHA1相關(guān)類:
System.Security.Cryptography.SHA1
System.Security.Cryptography.SHA1CryptoServiceProvider()
System.Web.Security.FormsAuthentication.HashPassword-ForStoringInConfigFile(strSource,"SHA1")
在ASP.NET類中,對(duì)于加密算法的實(shí)現(xiàn)過(guò)程我們無(wú)需了解,只要我們知道如何使用就可以了。以下示例是使用MD5算法對(duì)管理員密碼進(jìn)行Hash處理,然后向數(shù)據(jù)庫(kù)的管理員表中插入密碼加密后的信息記錄:insert into admin values('Zhang san', upper(right(sys.fn_varBinToHexStr(hashbytes('MD5','123456')),32)))
在服務(wù)器端驗(yàn)證用戶名和密碼:///
///驗(yàn)證用戶名與密碼
///
public bool CheckUserPassword(string userName,string password)
{
SqlParameter[]paras=new SqlParameter[2];
paras[0]= new SqlParameter("adminName",user-Name);
paras[1]=new SqlParameter("adminPwd",FormsAuthentication.HashPasswordForStoringInConfigFile(password,"MD5"));
return 0 } .NET所支持的加密技術(shù)[7]分為對(duì)稱密碼算法和非對(duì)稱密碼算法。對(duì)稱密碼算法包含DES,RC2,Rijndael,TripleDES;非對(duì)稱密碼算法包括:Digital Signature Algorithm(DSA),RSA。 基于角色的安全會(huì)詢問(wèn)某個(gè)用戶是不是處于指定角色中的問(wèn)題。如果該實(shí)體處于該角色中,他就可以安全地訪問(wèn)一個(gè)系統(tǒng)資源或者應(yīng)用程序特性。微軟在ASP.NET 2.0發(fā)行中加入了現(xiàn)成的安全憑證基礎(chǔ)結(jié)構(gòu),在憑證存儲(chǔ)中,每個(gè)用戶或角色僅限于應(yīng)用程序之內(nèi)。這樣就允許不同應(yīng)用程序使用一樣的憑證存儲(chǔ)而不會(huì)與彼此的用戶名或角色相沖突。 基于角色的安全技術(shù)實(shí)施步驟[8]: (1)組織好站點(diǎn)中的文件; (2)利用網(wǎng)站管理工具進(jìn)行安全配置; (3)利用控件創(chuàng)建安全頁(yè)。 本文分析了SQL注入攻擊的原理和存儲(chǔ)過(guò)程如何防止SQL注入攻擊,并且指出.NET開(kāi)發(fā)中的常用安全措施,對(duì)于.NET開(kāi)發(fā)初學(xué)者有很好的安全引導(dǎo)作用,也為下一步應(yīng)用開(kāi)發(fā)奠定了安全基礎(chǔ)。4.3 基于角色的安全
5 總結(jié)