在做安全配置前,我們先瞭解一下入侵者的攻擊手法。現在很流行注入攻擊,所謂注入攻擊,就是利用提交特殊地址將ASP中引用的正常SQL語句和入侵者所需要的SQL語句一併執行,使入侵者達到入侵的目的。現在更是有一些指令碼注入工具發布,使菜鳥也可以輕鬆完成對ASP的注入攻擊。那麼我們先來瞭解一下這些工具是怎樣注入的。
首先,入侵者會對一個網站確定可不可以進行注入,假設一篇文章的地址為:http://www.abc.com/news.asp?id=1一般會以提交兩個地址來測試,如:
http://www.abc.com/news.asp?id=1 and 1=1
http://www.abc.com/news.asp?id=1 and 1=2
第一個地址後面加了 and 1=1,構成的SQL語句也就變為了:Select * from 表單名 where id=1 and 1=1這句話要成立就必須and前後語句都成立。那麼前面的文章地址是可以訪問的,後面的1=1也是客觀成立的,那麼第一個地址就可以正常顯示;相反1=2是顯然不成立的,關鍵就看這步了,如果提交and 1=2頁面還是正常顯示說明他並沒有將and 1=2寫入SQL語句,此站也就不存在注入漏洞;但如果提交and 1=2之後返回了錯誤頁面則說明此網站將後面的語句帶入了SQL語句並執行了,也就說明他可以進行SQL注入。(註:如果地址後面跟的是news.asp?id='1'就得變為news.asp?id=1' and '1'='1來補全引號了)
那麼,知道可以注入後入侵者可以做什麼呢?
這裡就簡單的說一下,比如提交這樣的地址:
http://www.abc.com/news.asp?id=1 and exists (select * from 表名 where 列名=資料)
根據返回的正確或錯誤頁面來判斷猜的表名和列名是否正確,具體實現時是先猜表名再猜列名。當猜出表名和列名之後還可以用ASC和MID函數來猜出各列的資料。MID函數的格式為:mid(變數名,第幾個字元開始讀取,讀取幾個字元),比如:mid(pwd,1,2)就可以從變數pwd中的第一位開始讀取兩位的字元。ASC函數的格式為:ASC("字串"),如:asc("a")就可以讀出字母a的ASCII碼了。那麼實際應用的時候就可以寫為:asc(mid(pwd,1,1))這樣讀取的就是pwd列的第一個字元的ASCII碼,提交: asc(mid(pwd,1,1))>97以返回的頁面是否為正確頁面來判斷pwd列的第一個字元的ASCII碼是否大於97(a的ASCII碼),如果正確就再試是否小於122(z的ASCII碼)……這樣慢慢縮小字元的ASCII碼的範圍,猜到真實的ASCII碼也只是時間的問題。一位一位的猜就可以得到資料庫中的使用者名稱和密碼了。還有一種ASP驗證缺陷——就是使用者名稱和密碼都輸'or '1'='1,構造SQL語句Select * form 表單名 where username='' or '1'='1' and pwd='' or '1'='1'就可以達到繞過密碼驗證的目的。
說了那麼多,其實防範的方法很簡單,我們把特殊字元(如and、or、'、")都禁止提交就可以防止注入了。ASP傳輸資料分為get和post兩種, get是通過將資料添加到URL後提交的方式,post則是利用郵寄資訊資料欄位將資料傳送到伺服器。
那麼,我們先來看看如何將get方式提交資料中的特殊字元過濾。首先要知道,IIS是以字串的形式將get請求傳給asp.dll的,在將資料傳遞給Request.QueryString之後,asp解析器會解析出Request.QueryString的資訊,然後跟據"&"來分出各個數組內的資料。現在我們要讓get方式不能提交以下字元:
'、and、exec、insert、select、delete、update、count、*、%、chr、mid、master、truncate、char、declare
SQL通用防注入程式是由Firefox的楓知秋編寫的,功能相當完善的防注入代碼。它能對定義的過濾字元實現get提交的過濾,並能記錄攻擊者的IP提交的資料資訊。使用時只須在要防注入的檔案頭中加入代碼<!--#Include File="WrSky_Sql.Asp"-->可以實現對變數的過濾。如果在資料庫連接檔案(如conn.asp)後加入程式碼,則可以實現整站的變數過濾,從而達到防注入的效果。
<%
dim sql_leach,sql_leach_0,Sql_DATA,SQL_Get,Sql_Post
sql_leach = "',and,exec,insert,select,delete,update,count,*,%,chr,mid,master,truncate,char,declare"
sql_leach_0 = split(sql_leach,",")
If Request.QueryString<>"" Then
For Each SQL_Get In Request.QueryString
For SQL_Data=0 To Ubound(sql_leach_0)
if instr(Request.QueryString(SQL_Get),sql_leach_0(Sql_DATA))>0 Then
Response.Write "請不要嘗試進行SQL注入!"
Response.end
end if
next
Next
End If
If Request.Form<>"" Then
For Each Sql_Post In Request.Form
For SQL_Data=0 To Ubound(sql_leach_0)
if instr(Request.Form(Sql_Post),sql_leach_0(Sql_DATA))>0 Then
Response.Write "請不要嘗試進行SQL注入!"
Response.end
end if
next
next
end if
%>
防止暴庫的辦法,在資料庫檔案前面加上On Error Resume Next
<%
On Error Resume Next
dim conn,connstr,db
%>.