SQL關(guān)于特殊字符處理的基本方法
當(dāng)前位置:點(diǎn)晴教程→知識(shí)管理交流
→『 技術(shù)文檔交流 』
一定要對(duì)用戶可能輸入的諸如引號(hào),尖括號(hào)等特殊字符給予足夠重視,它們可能引發(fā)嚴(yán)重的安全問(wèn)題。SQL注入的基本手法之一,就是利用對(duì)單引號(hào)未加過(guò)濾的安全漏洞。 用戶的輸入無(wú)非兩個(gè)用途:對(duì)數(shù)據(jù)庫(kù)操作或顯示在頁(yè)面上,下面分別對(duì)這兩種情況下特殊字符的處理加以說(shuō)明。 1. 對(duì)數(shù)據(jù)庫(kù)操作 用戶輸入的數(shù)據(jù)用于對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作時(shí),又分為兩種情況,一是進(jìn)行寫庫(kù)操作,二是作為查詢條件。 1.1 寫庫(kù)操作 (insert及update都視為寫庫(kù)操作,這果以insert為例說(shuō)明,update的處理相同) 一般采用insert語(yǔ)句或AddNew方法兩種方式進(jìn)行寫庫(kù)操作,我們先來(lái)看insert語(yǔ)句: DIM username,sqlstr username = trim(Request.Form("uname")) sqlstr = "insert into [userinfo] (username) values ('"& username &"')" 以SQL Server為例,使用這種方式寫庫(kù),如果username中含用單引號(hào)('),會(huì)出錯(cuò)。使用下面的自定義函數(shù),可以將單引號(hào)進(jìn)行轉(zhuǎn)換: Rem 轉(zhuǎn)換SQL非法字符 function SQLEncode(fString) if isnull(fString) then SQLEncode = "" exit function end if SQLEncode=replace(fString,"'","''") end function 以上函數(shù)將一個(gè)單引號(hào)轉(zhuǎn)換為兩個(gè)連續(xù)的單引號(hào),數(shù)據(jù)庫(kù)能夠接受,并以一個(gè)單引號(hào)寫入。SQL語(yǔ)句改為: sqlstr = "insert into [userinfo] (username) values ('"& SQLEncode(username) &"')" 再來(lái)看AddNew方法: DIM username username = trim(Request.Form("uname")) 'MyRst為Recordset對(duì)象,MyConn為Connection對(duì)象 MyRst.open "[userinfo]",MyConn,0,3 MyRst.AddNew MyRst("username").Value = username MyRst.Update MyRst.Close 使用這種方式寫庫(kù)時(shí),不必調(diào)用SQLEncode()對(duì)單引號(hào)進(jìn)行轉(zhuǎn)換,數(shù)據(jù)庫(kù)會(huì)自行處理。 對(duì)于存儲(chǔ)過(guò)程的的參數(shù),同樣不必進(jìn)行單引號(hào)的轉(zhuǎn)換。 建議大家利用存儲(chǔ)過(guò)程進(jìn)行操作,好處嘛,我在《ASP與存儲(chǔ)過(guò)程》一文中已做了闡述。否則,建議使用AddNew方法寫庫(kù),好處不僅僅在于避免對(duì)單引號(hào)進(jìn)行處理,本文對(duì)此不作深入探討。 1.2 用戶輸入做為查詢條件 如果用戶輸入的數(shù)據(jù)作為查詢條件出現(xiàn)在where子句中,不論該where子句屬于update語(yǔ)句、delete語(yǔ)句還是select語(yǔ)句,都要對(duì)單引號(hào)進(jìn)行轉(zhuǎn)換。 2. 用戶輸入的數(shù)據(jù)作為輸出,顯示在頁(yè)面上 我們這里只討論不允許用戶使用HTML代碼的情況,也就是說(shuō),即使用戶輸入了HTML代碼,這些數(shù)據(jù)也不會(huì)以HTML代碼的形式顯示。至于允許用戶使用HTML代碼的情況,比較復(fù)雜,以后專文探討。 用戶輸入的數(shù)據(jù)是絕對(duì)不可以不加處理,原樣顯示的。如果其中包含HTML或js代碼,使你的頁(yè)面混亂不堪倒是小事,甚至可以格掉你的硬盤。 輸出顯示在頁(yè)面上的數(shù)據(jù),有可能是用戶的直接輸入,或是取自數(shù)據(jù)庫(kù)??梢钥吹揭陨显谌霂?kù)時(shí)的處理只是轉(zhuǎn)換了單引號(hào),對(duì)尖括號(hào),雙引號(hào)等特殊字符并未處理,我們放在輸出的時(shí)候再進(jìn)行處理。 ASP中的server.HTMLEncode()方法可以將許多字符轉(zhuǎn)換為“HTML字符”,如將<轉(zhuǎn)換為<,將>轉(zhuǎn)換為>等等。 在數(shù)據(jù)顯示在頁(yè)面上之前,可以用server.HTMLEncode()對(duì)其進(jìn)行轉(zhuǎn)換。但是該方法不會(huì)對(duì)回車,空格進(jìn)行轉(zhuǎn)換,這樣就造成以下問(wèn)題:如果用戶是通過(guò)textarea控件輸入的數(shù)據(jù),輸出時(shí)將不會(huì)保留原有格式,不僅沒(méi)有回車換行,多個(gè)空格也只會(huì)顯示為一個(gè)。為了解決這個(gè)問(wèn)題,我們使用以下自定義函數(shù): Rem 轉(zhuǎn)換HTML非法字符,用于輸出顯示時(shí) function HTMLEncode(fString) if not isnull(fString) then fString = Replace(fString, ">", ">") fString = Replace(fString, "<", "<") fString = Replace(fString, CHR(34), """) '雙引號(hào) fString = Replace(fString, CHR(39), "'") '單引號(hào) fString = Replace(fString, CHR(32)&CHR(32), " ") '空格 fString = Replace(fString, CHR(9), " ") 'tab鍵值 fString = Replace(fString, CHR(10), "<br>") '換行 fString = Replace(fString, CHR(13), "") '回車 HTMLEncode = fString end if end function 調(diào)用以上函數(shù),輸出通過(guò)textarea控件輸入的數(shù)據(jù),會(huì)得到滿意的結(jié)果。 如果數(shù)據(jù)輸出在表單控件中,不論是何種控件,都可利用server.HTMLEncode()方法轉(zhuǎn)換字符,即使是對(duì)于textarea控件,也不會(huì)產(chǎn)生問(wèn)題。雖然回車空格沒(méi)有被轉(zhuǎn)換,但在該控件中可以被識(shí)別。但是,server.HTMLEncode()方法不轉(zhuǎn)換單引號(hào)。所以,控件的值一定要使用雙引號(hào): <input type=text name=uname value=""" & server.HTMLEncode(username) & """> 否則,如果用戶輸入的是 '' onclick=javascript:.... ,以上代碼將顯示為: <input type=text name=uname value='' onclick=javascript:...> 而javascript命令可以做的事情實(shí)在是太多了。 以上,通過(guò)用戶輸入數(shù)據(jù)的兩種用途,對(duì)特殊字符的處理做了大概的說(shuō)明。還有一種情況:用戶的輸入作為GET請(qǐng)求的參數(shù)值。比如通過(guò)以下URL向服務(wù)器發(fā)送請(qǐng)求:test.asp?username=MyName 我一般只把數(shù)值型的數(shù)據(jù)做此類提交,并在接收時(shí)對(duì)數(shù)據(jù)類型做驗(yàn)證。若是字符型的數(shù)據(jù),如何處理特殊字符呢?有興趣的朋友思考一下吧,呵呵。 有些朋友喜歡用JAVAScript過(guò)濾特殊字符,而且限制輸入的字符很多。我不建議這么做,一是JAVAScript是客戶端運(yùn)行的,不可靠。要知道,對(duì)服務(wù)器的請(qǐng)求是可以偽造的,偽造者可不會(huì)加上你的JAVAScript代碼;二是JAVAScript不太友好;三者,實(shí)際上沒(méi)有必要限制那么多字符,限制太多,用戶會(huì)害怕的。 總結(jié)一下我對(duì)特殊字符處理的經(jīng)驗(yàn)吧: 1. 對(duì)接收到的數(shù)據(jù)類型進(jìn)行驗(yàn)證;
2. 盡量通過(guò)存儲(chǔ)過(guò)程對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作; 3. 如上一點(diǎn)不可行,盡量使用AddNew方法寫庫(kù); 4. 對(duì)作為查詢條件的數(shù)據(jù),使用自定義函數(shù)SQLEncode()轉(zhuǎn)換單引號(hào); 5. 表單控件的值,一定要用雙引號(hào)引起來(lái); 6. 在表單控件中顯示數(shù)據(jù)時(shí),使用server.HTMLEncode()方法轉(zhuǎn)換字符; 7. 對(duì)于通過(guò)textarea提交的數(shù)據(jù),使用自定義函數(shù)HTMLEncode()轉(zhuǎn)換字符并保持格式; 8. 盡量避免使用Request()接收數(shù)據(jù),應(yīng)使用Request.Form()或Request.QueryString(); 9. 盡量避免通過(guò)URL傳遞字符參數(shù)(只用此方式傳遞數(shù)值參數(shù)) 該文章在 2011/2/16 0:02:35 編輯過(guò) |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |