SQL注入漏洞的檢測與防範技術

提 要   本文從SQL注入的基本概念和注入原理入手,分析總結了SQL注入漏洞的檢測及其防範技術措施。
關鍵詞  SQL注入漏洞 檢測 防範技術

引 言
   近幾年來隨着計算機網絡和WEB技術的飛速發展,Internet已經成爲人們溝通信息和協同工作的有效工具,氣象行業也是如此。僅半年多的時間,筆者就先後編寫了淮北先鋒網、氣象網、勞務網、星火網、農網信息站等五個網站的應用程序,並已開通運行,這主要得益於應用B/S模式和ASP技術的易操作性。但隨之而來的網絡安全問題也越來越引起關注。前不久,一位網友告知他通過SQL注入方式獲取了我們某個網站某個功能模塊的管理員帳戶和密碼,這使我大吃一驚,經查的確存在SQL注入漏洞,這才使我不得不放下手頭的工作,研究解決這個問題。後來發現,我省氣象部門的不少網站均存在這個漏洞,故在這裏班門弄斧,談談SQL注入漏洞的檢測與防範措施,供參考。

1 SQL注入的基本概念和注入原理
    ASP是當今進行WEB編程的最流行工具之一,國內的網站用ASP+Access或SQLServer的佔70%以上,PHP+MySQL佔20%,其它的不足10%。因爲ASP編程的門檻低,新手容易上路。但在安全性方面,新手最容易忽略的問題就是SQL注入漏洞的問題。相當大一部分程序員在編寫代碼的時候,根本不對用戶輸入數據的合法性進行判斷,至使應用程序存在安全隱患。
    所謂SQL注入(SQL Injection),就是利用某些WEB應用程序對用戶輸入數據的合法性檢測不嚴或不檢測的特點,故意從客戶端提交一段特殊的數據庫查詢代碼,根據程序返回的結果,達到收集程序、數據庫及服務器的信息,獲取想得到而通過正常途徑無法得到的資料,使整個網站服務器失控甚至對網站進行破壞性***的目的。
    由於SQL注入是從正常的WWW端口訪問,而且表面看起來跟一般的Web頁面訪問沒什麼區別,所以目前的防火牆都不會對SQL注入發出警報,如果管理員沒有查看IIS日誌的習慣,可能被***很長時間都不會發覺,這也是SQL注入能夠成功的原因之一。

2 SQL注入漏洞的檢測
    SQL注入***的漏洞並非系統造成的,而是程序員在編程中忽略了安全因素。怎樣對網頁的SQL注入漏洞進行測試呢?這裏介紹一些簡單通用的方法,具體步驟如下:
    第一步:設置瀏覽器的屬性。即在桌面上打開“Internet Explorer”的屬性或通過控制面板打開“Internet選項”或當IE瀏覽器已打開時選擇“IE菜單=>工具=>Internet選項=>高級”下拉菜單,將“顯示友好HTTP 錯誤信息”前面的勾去掉。否則,無論服務器返回什麼錯誤,IE都顯示爲HTTP 500服務器錯誤,而不能獲得更多的提示信息。
    第二步:打開一個帶數據庫操作的網頁。
這種頁面在IE地址欄顯示的信息類似於:“http://www.xxx.com/xxx/show.asp?ID=123”。
    有的頁面隱含了瀏覽器的地址欄等信息,僅顯示頁面內容,這時只要用鼠標右鍵點擊該頁面並選中“屬性”,即可查出類似於:“http://www.xxx.
    Com/xxx/show.asp?ID=123”的地址信息,將它複製到IE的地址欄同樣可以顯示出相同的頁面內容。
這個頁面的執行過程是這樣的,瀏覽器將這個網址提交到服務器後,服務器將進行類似Select * from 表名 where 字段="&ID的查詢(ID即客戶端提交的參數,本例是123),再將查詢結果返回給客戶端並在瀏覽器中顯示出來。
    第三步:檢測SQL注入漏洞。
    SQL注入的形式一般有兩種:一種是發生在 ASP 服務器根據 querystring 參數動態生成網頁時,即從IE的地址欄構建特殊的 SQL 指令語句,由 URL 中的 querystring 參數注入。如:通過http://www.xxx.com/xxx/show.asp?ID=123; DELETE FROM tblArticles ” 之類的 URL 來訪問 Web 網站,一旦***成功就有可能達到刪除數據庫中某個表格的目的。另一種是當 Web 網站採用form或cookies來收集訪問者的用戶名和密碼以確認他有足夠權限訪問某些保密信息的時候,在這種情況下表單被髮送到 Web 服務器進行處理,服務器端的ASP 腳本根據form或cookies提供的信息生成 SQL 指令語句提交到 SQL 服務器,並通過分析判斷該用戶名/密碼組合是否有效。此時***者可能會在form或cookies的用戶名或密碼欄中輸入包含“ or ”和“=” 等特殊字符組合。如果存在注入漏洞,提交給數據庫的 SQL 指令就可能是代碼:
    SELECT * FROM Users WHERE Username='a' or 1=1 and Password ='a' or 1=1這樣,SQL 服務器將返回 Users 表格中的所有記錄,而 ASP 腳本將會因此而誤認爲***者的輸入符合 Users 表格中的第一條記錄,從而允許***者以該用戶的名義登入網站。
    無論那一種SQL注入形式,之所以能夠注入成功都是因爲應用程序存在漏洞,怎樣才能順利檢測出這種SQL注入漏洞呢? 
針對SQL注入的第一種形式,漏洞檢測的方法可分爲三種情況。
2.1 傳入參數是數字型時SQL注入漏洞的檢測方法
    當查找到URL類似於:http://www.xxx.com/xx
    x/show.asp?ID=123的頁面時,其中的ID=123表明參數是數字型的,構成的SQL語句原貌大致爲: Select * from 表名 where 字段=123。檢測漏洞的方法爲:在IE地址欄分別輸入以下三個URL參數並執行,比較其執行結果。
    ① http://www.xxx.com/xxx/show.asp?ID=123
    ②http://www.xxx.com/xxx/show.asp?ID=123 ;and 1=1
    ③http://www.xxx.com/xxx/show.asp?ID=123 ;and 1=2 
    其中,①是一個正常的URL參數,②和③分別在其後添加了用來檢測漏洞的特殊字符組合,根據上面三個網址返回的結果就知道是否存在SQL注入漏洞。
    存在SQL注入漏洞的表現: 
    ① 正常顯示(這是必然的,不然就是程序有錯誤了) 
    ② 正常顯示,內容基本與①相同 
    ③ 提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容爲空(程序加了on error resume next) 
    沒有SQL注入漏洞的表現:
    ①同樣正常顯示,②和③一般都會顯示程序所定義的錯誤提示,或提示類型轉換時出錯。
2.2 傳入參數是字符型時SQL注入漏洞的檢測方法
    當查找到 URL 類似於:http://www.xxx.com/x
    xx/show.asp? type=經典小品 的頁面時,其中的“type =經典小品”表明參數是字符型的,構成的SQL語句大致爲: Select * from 表名 where 字段='經典小品'。檢測漏洞的方法爲:在IE地址欄分別輸入以下三個URL參數並執行,比較其執行結果。
    ① http://www.xxx.com/xxx/show.asp? type =經典小品
    ② http://www.xxx.com/xxx/show.asp? type =經典小品' or ''='
    ③ http://www.xxx.com/xxx/show.asp? type =經典小品'or ''='1' '
    存在SQL注入漏洞的表現: 
    ① 正常顯示
    ②正常顯示,且顯示結果爲數據表中的全部內容。
    ③提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容爲空(程序加了on error resume next) 
    沒有SQL注入漏洞的表現:
    ①同樣正常顯示,②和③一般都會顯示程序所定義的錯誤提示,或提示類型轉換時出錯。
2.3 傳入參數是搜索型時SQL注入漏洞的檢測方法
    當查找到 URL 類似於:http://www.xxx.com/x
    xx/show.asp? Keyword=關鍵字的頁面時,構成的SQL語句大致爲: Select * from 表名 where 字段 like '%關鍵字%',其中的“字段 like '%關鍵字%'”表明參數是搜索型的。檢測漏洞的方法爲在IE地址欄輸入:
http://www.xxx.com/xxx/show.asp? Keyword=關鍵字' and [查詢條件] and '%25'='
    當提示BOF或EOF(程序沒做任何判斷時)、或提示找不到記錄(判斷了rs.eof時)、或顯示內容爲空(程序加了on error resume next)時表明有SQL注入漏洞;否則如果顯示程序所定義的錯誤提示,或提示類型轉換時出錯,則表明沒有SQL注入漏洞。
2.4 通過form或cookies傳入參數時SQL注入漏洞的檢測方法
    針對上述SQL注入的第二種形式,即當 Web 網站採用表單來收集訪問者的用戶名和密碼以確認他是否有足夠權限訪問某些保密信息時,檢測漏洞的方法是:在表單的用戶名和密碼欄中分別輸入“a 'or'1=1 ”等特殊字符。於是,提交給數據庫的 SQL 指令就可能是代碼:SELECT * FROM 表名 WHERE Username='a' or 1=1 and Password ='a' or 1=1,這時如果存在明顯的SQL注入漏洞則SQL 服務器將返回表格中的所有記錄,而 ASP 腳本將會因此而誤認爲***者的輸入符合表格中的第一條記錄,從而允許***者以該用戶的名義登入網站;如果顯示程序所定義的錯誤提示,或提示類型轉換時出錯,則表明沒有這方面的SQL注入漏洞。

3 防範SQL注入的措施
    檢測發現SQL注入漏洞,就應立即採取必要的防範措施來堵住這個漏洞,確保網站運行安全。通過分析我們注意到,存在SQL注入漏洞的根源就是在程序中缺少對用戶輸入數據的合法性進行嚴格的判斷,加上WEB服務器的訪問權限和出錯提示設置不當造成的。防範SQL注入的措施可以歸結爲以下幾個方面:
3.1 程序員要採取的措施
    程序員可以從兩個方面採取措施以堵住SQL注入的漏洞:一個是對用戶提交的數據進行嚴格的審查,即採用各種安全手段監控來自 ASP Request 對象 (Request 、 Request.QueryString 、 Request.Form 、 Request.Cookies 和 Request.ServerVariables) 的用戶輸入,以確保 SQL 指令的可靠性;另一個是給用戶密碼進行加密處理。
3.1.1 查堵URL端的漏洞
    審查用戶端通過URL提交的參數中是否含有“and、or、'、"、:、;、exec、insert、select、delete、from、update、count、user、xp_cmdshell、add、net、asc(、char(、chr( 、drop、table、truncate 、%、mid”,等用於SQL注入的常用字符或字符串(其中最關鍵的是單引號(')、分號(;)、空格符( )及轉義字符(asc()、(chr()、(char()、(%)),一經發現立即停止執行ASP並給出警告信息或轉向出錯頁面,比較簡單有效的方法是將下列代碼保存爲KSQLI.ASP存放在網站根目錄下,然後在每個含有接收用戶端URL提交參數的程序(最高效的是在每個數據庫鏈接文件conn.asp)中用<!--#include file="../ksqli.asp"-->引入即可。KSQLI.ASP的代碼如下:
<%
Dim K_Url,K_a,K_x,K_Cs(),strurl
On Error Resume Next
K_Url=Request.ServerVariables("QUERY_STRING")
K_a=split(K_Url,"&")
redim K_Cs(ubound(K_a))
On Error Resume Next
for K_x=0 to ubound(K_a)
K_Cs(K_x)=Left(K_a(K_x),instr(K_a(K_x),
"=")-1)
Next
For K_x=0 to ubound(K_Cs)
If K_Cs(K_x)<>"" Then
strurl=LCase(Request(K_Cs(K_x)))
If Instr(strurl,"'")<>0 or Instr(strurl,";")<>0 or Instr(strurl," ")<>0 or Instr(strurl," %20")<>0 or Instr(strurl," %25")<>0 or Instr(strurl,"chr(")<>0 or
Instr(strurl,"asc(")<>0 orInstr(strurl,"char(")<>0 Then
Response.Write "<Script Language=JavaScript
>Alert('URL中含有非法字符串!');window.close();
</Script>"
Response.End
End If
End If
Next
%> 
    注:以上代碼足以阻擋大多數***者,而且不大影響程序的執行速度;您可以在if語句中加入前面列舉的其它用於SQL注入的常用字符或字符串,使防範更嚴密,但對程序的執行速度有一定影響。
3.1.2 查堵form或cookies的漏洞
    既然***者是通過form或cookies提交包含“ or ”和“=” 等特殊字符,那麼我們的防範措施就是在這部分程序中加入檢查或過濾這些特殊字符的代碼,以實現安全目的。方法是在使用: paraname=
Request.form()或paraname=Request. Cookies()獲取用戶名和密碼後加入代碼:
If instr(paraname," ")>0 or instr(paraname," or ")>0 or instr(paraname,"=")>0 or instr(paraname,"'")
>0 or instr(paraname,";")>0 then
Response.Write "<Script Language=JavaScript>alert('用戶參數中含有非法字符串!'); history.back();</Script>"
Response.End
End If
    含義:假如在用戶參數paraname中找到了(空格)、( or )、(=)、(')與(;)等非法字符,就立即執行then 後的語句,終止ASP的運行,***者也就無法進行SQL注入了。 
3.1.3 給用戶密碼進行加密處理
    程序員要做的另一件事是給用戶密碼加密,一般用MD5加密較好。MD5沒有反向算法,不能解密,人家即使知道經加密後存在數據庫裏的像亂碼一樣的密碼,他也沒辦法知道原始密碼。除非使用UPDATE方法用他的密碼代替你的密碼,但這個操作在3.1.1和3.1.2中已經堵死了。要注意的是,正因爲MD5加密以後的信息不可以解密,如果用戶丟失密碼,任何人都很難找到用戶原來的密碼,這時候,網站也就相應的失去了爲用戶提供其他信息來取得忘記的密碼的功能。另外,採用這樣的加密方式,必須完全修改以前的用戶資料,要求用戶完全重新註冊,或將數據庫中相關字段經MD5加密計算後再重新保存,這是MD5加密方法比較困難的一個地方,請權衡使用。鑑於篇幅,MD5加密的具體做法請參考有關資料,這裏不作闡述。
3.2 服務器管理員要採取的措施
    精心配置IIS打造一個安全Web服務器是一項科學嚴謹的工作,事關網絡安全之首要,也是服務器管理員的神聖職責,具體做法請參見有關資料。針對防範SQL注入要做的主要是把IIS設置成不管出什麼樣的ASP錯誤,只給出一種錯誤提示信息,即http 500錯誤,再小心設置數據庫用戶權限。這樣人家就無法***了。IIS設置參見圖1。首先把500:100這個錯誤的默認提示頁面C:\WINDOWS\He
lp\iisHelp\common\500-100.asp改成C:\WINDOW
SHelp\iisHelp\Common\500.htm。
    其次還應在IIS中爲每個網站設置好執行權限,一般情況下有"純腳本"權限就夠了,對於那些存放網站後臺管理中心上傳文件的目錄執行權限設爲"無"更好,這樣可以防止人家上傳運行ASP***。

 

 


    第三,當使用MS_SQL數據庫時,一般把權限設爲PUBLIC就夠了,注意不能讓用戶隨便得到SA級別的權限。ACCESS則沒有用戶權限配置這一步驟。

4 結束語
    SQL注入是網絡安全領域的新事物,但發展快危害大,而且經常被一些網站開發或網頁設計人員所忽視。只要我們提高認識,在設計開發和網站運行的過程中隨時注意查堵SQL注入漏洞,不給***者以可乘之機,就可以在很大程度上提高網絡的運行安全。本文所作的一些研究和總結,希望能給讀者以啓發和借鑑。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章