說到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編碼就是。那麼漢字的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編碼#替換掉#。我本來企圖利用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就可以了。
呵呵,謝謝閣下耐著性子看完我的文章^_^
lake2