當前位置:開發者網絡 >> 技術教程 >> ASP教程 >> 數據庫相關 >> 內容
精彩推薦
分類最新教程
分類熱點教程
    
URL編碼與SQL注射
作者:未知
日期:2005-04-26
人氣:
投稿:(轉貼)
來源:未知
字體:
收藏:加入瀏覽器收藏
以下正文:
說到url編碼,你或許會想起N年前的url編碼漏洞。可惜我是「生不逢時」啊,我接觸網絡時,那個漏洞早就絕跡咯。

言歸正傳,URL 編碼是什麼東東呢?看看我從網上抄的定義:

引用: url編碼是一種瀏覽器用來打包表單輸入的格式。瀏覽器從表單中獲取所有的name和其中的值 ,將它們以name/value參數編碼(移去那些不能傳送的字符, 將數據排行等等)作為URL的一部分或者分離地發給服務器。不管哪種情況, 在服務器端的表單輸入格式樣子像這樣:

theName=Ichabod+Crane&gender=male&status=missing&headless=yes

URL編碼遵循下列規則: 每對name/value由&符分開;每對來自表單的name/value由=符分開。如果用戶沒有輸入值給這個name,那麼這個name還是出現,只是無值。任何特殊的字符(就是那些不是簡單的七位ASCII,如漢字)將以百分符%用十六進制編碼,當然也包括象 =, &, 和 % 這些特殊的字符。


呵呵,明白了吧,其實url編碼就是一個字符ascii碼的十六進制。不過稍微有些變動,需要在前面加上「%」。比如「\」,它的ascii碼是92,92的十六進制是5c,所以「\」的url編碼就是%5c。那麼漢字的url編碼呢?很簡單,看例子:「胡」的ascii碼是-17670,十六進制是BAFA,url編碼是「%BA%FA」。呵呵,知道怎麼轉換的了吧。

URL編碼平時我們是用不到的,因為IE會自動將你輸入到地址欄的非數字字母轉換為url編碼。所以對於瀏覽器來說http://blog.csdn.net/l%61ke2與http://blog.csdn.net/lake2是等效的(注意,第一個url我用%61替換了a)。呵呵,或許你已經想起了,有人提出數據庫名字裡帶上「#」以防止被下載,因為IE遇到#就會忽略後面的字母。破解方法很簡單——用url編碼%23替換掉#。我本來企圖利用url編碼來躲過注射檢查的,不過失敗了,因為服務器端會將url編碼轉換成字符的。

等等,好像跑題了啊,呵呵,不好意思:)

現在SQL注射非常流行,所以就有人寫了一些防注射的腳本。當然啦,思路不一樣,效果大不同。各位看官請看下面的××SQL通用防注入asp版部分代碼。

Fy_Url=Request.ServerVariables("QUERY_STRING")
Fy_a=split(Fy_Url,"&")
redim Fy_Cs(ubound(Fy_a))
On Error Resume Next
for Fy_x=0 to ubound(Fy_a)
Fy_Cs(Fy_x) = left(Fy_a(Fy_x),instr(Fy_a(Fy_x),"=")-1)
Next
For Fy_x=0 to ubound(Fy_Cs)
If Fy_Cs(Fy_x)<>"" Then
If Instr(LCase(Request(Fy_Cs(Fy_x))),"and")<>0 then
Response.Write "出現錯誤!"
Response.End
End If
End If
Next


它的思路就是先獲得提交的數據,以「&」為分界獲得並處理name/value組,然後判斷value裡是否含有定義的關鍵字(這裡為求簡便,我只留下了「and」),有之,則為注射。

乍一看去,value被檢查了,似乎沒有問題。呵呵,是的,value不會有問題,可是,name呢?

它的name/value組值來自於Request.ServerVariables("QUERY_STRING"),呵呵,不好意思,這裡出問題了。Request.ServerVariables("QUERY_STRING")是得到客戶端提交的字符串,這裡並不會自動轉換url編碼,哈哈,如果我們把name進行url編碼再提交的話,呵呵,那就可以繞過檢查了。比如參數是ph4nt0m=lake2 and lis0,此時程序能夠檢測到;如果提交%50h4nt0m=lake2 and lis0(對p進行url編碼),程序就會去判斷%50h4nt0m的值,而%50h4nt0m會被轉換為ph4nt0m,所以%50h4nt0m值為空,於是就繞過了檢測。

等等,為什麼既然name不解碼可以繞過檢查而value就不能繞過呢?因為value的值取自Request(Fy_Cs(Fy_x)),這個服務器就會解碼的。

程序怎麼改進呢?只要能夠得到客戶端提交的數據是解碼後的就可以了,把得到name的語句改為For Each SubmitName In Request.QueryString就可以了。
相關文章: