数学建模社区-数学中国

标题: URL编码与SQL注射 [打印本页]

作者: 韩冰    时间: 2004-11-22 23:43
标题: URL编码与SQL注射
<>说到url编码,你或许会想起N年前的url编码漏洞。可惜我是"生不逢时"啊,我接触网络时,那个漏洞早就绝迹咯。
1 H3 ~5 ?6 l  b2 _( x- i+ p) U# [- [2 ?. V5 \
言归正传,URL 编码是什么东东呢?看看我从网上抄的定义:( ], Z# Y( R- A1 T) C% z$ M" v
1 _9 s% v# }- J( d
引用: </P>; W+ |% E$ Y: H* a& c: g/ S
url编码是一种浏览器用来打包表单输入的格式。浏览器从表单中获取所有的name和其中的值 ,将它们以name/value参数编码(移去那些不能传送的字符, 将数据排行等等)作为URL的一部分或者分离地发给服务器。不管哪种情况, 在服务器端的表单输入格式样子象这样: ) m3 ~, U3 j/ Q( h
% A. y# [! t4 N4 O4 {; D2 K- I
theName=Ichabod+Crane&amp;gender=male&amp;status=missing&amp;headless=yes+ ~  E% S: |4 A8 F

% g6 l& [. F% j6 {6 r3 P# I, Y* q) [URL编码遵循下列规则: 每对name/value由&amp;符分开;每对来自表单的name/value由=符分开。如果用户没有输入值给这个name,那么这个name还是出现,只是无值。任何特殊的字符(就是那些不是简单的七位ASCII,如汉字)将以百分符%用十六进制编码,当然也包括象 =, &amp;, 和 % 这些特殊的字符。
0 A. j7 O5 j8 N- C3 s$ p5 Y4 a8 m8 `% L/ U' D
呵呵,明白了吧,其实url编码就是一个字符ascii码的十六进制。不过稍微有些变动,需要在前面加上"%"。比如"\",它的ascii码是92,92的十六进制是5c,所以"\"的url编码就是%5c。那么汉字的url编码呢?很简单,看例子:"胡"的ascii码是-17670,十六进制是BAFA,url编码是"%BA%FA"。呵呵,知道怎么转换的了吧。# z, u9 Z: y9 u/ x, V
! ~4 A. Y( \& Q; o
URL编码平时我们是用不到的,因为IE会自动将你输入到地址栏的非数字字母转换为url编码。所以对于浏览器来说http://blog.csdn.net/l%61ke2与http://blog.csdn.net/lake2是等效的(注意,第一个url我用%61替换了a)。呵呵,或许你已经想起了,有人提出数据库名字里带上"#"以防止被下载,因为IE遇到#就会忽略后面的字母。破解方法很简单——用url编码%23替换掉#。我本来企图利用url编码来躲过注射检查的,不过失败了,因为服务器端会将url编码转换成字符的。
/ M# b. r4 V$ b) x7 d6 c2 y/ J+ d- R) F7 ~5 \9 y
等等,好像跑题了啊,呵呵,不好意思:)( b1 F3 C4 t5 ]# U$ v& V7 z+ G$ N

4 f% ?* L2 Y8 j* B. l9 R( X" e现在SQL注射非常流行,所以就有人写了一些防注射的脚本。当然啦,思路不一样,效果大不同。各位看官请看下面的××SQL通用防注入asp版部分代码。
. i! G1 r0 a& G  y% n
8 c) Z/ x5 z8 h5 t- b2 n3 }# dFy_Url=Request.ServerVariables("QUERY_STRING")
( j$ z7 [. [) oFy_a=split(Fy_Url,"&amp;")
. b/ n  f! l1 m8 h" G: \redim Fy_Cs(ubound(Fy_a))
: H( j9 D3 h- i- jOn Error Resume Next
) P( Y: v$ W& H( b; h. D. G) q5 i( Gfor Fy_x=0 to ubound(Fy_a)3 I% w0 [5 e4 I# S
Fy_Cs(Fy_x) = left(Fy_a(Fy_x),instr(Fy_a(Fy_x),"=")-1)& O7 u- K/ \) Q: x) w! y6 A+ N
Next
/ [) A2 O2 W5 VFor Fy_x=0 to ubound(Fy_Cs)
; C1 T+ }" {! b7 z( E. e8 bIf Fy_Cs(Fy_x)&lt;&gt;"" Then$ g) C6 ]+ \2 d' V) k
If Instr(LCase(Request(Fy_Cs(Fy_x))),"and")&lt;&gt;0 then
8 n$ Q( }" i$ o) X1 AResponse.Write "出现错误!"
! o' w9 A" y* P- V+ wResponse.End
+ o3 h6 s0 a! M6 Z* o. ZEnd If: a8 O0 k/ e) o3 M9 K0 G
End If
+ _* _  }/ Y9 S( f! d' x# Q# GNext
8 `6 l1 ~5 v' L5 v& O  u/ G% Z4 {- d' C# O

. g/ |' v; g- x* B( |, ?它的思路就是先获得提交的数据,以"&amp;"为分界获得并处理name/value组,然后判断value里是否含有定义的关键字(这里为求简便,我只留下了"and"),有之,则为注射。
- e% \' T% F/ x. u
% k9 y' I+ V  F! t乍一看去,value被检查了,似乎没有问题。呵呵,是的,value不会有问题,可是,name呢?
! L2 {8 t) B7 c: g+ G. e8 ?  D& q8 Z: e! O* H6 X2 r& z
它的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值为空,于是就绕过了检测。6 t- `) k  Y" a: O

& ^; c' Y% }9 S" ?" ^等等,为什么既然name不解码可以绕过检查而value就不能绕过呢?因为value的值取自Request(Fy_Cs(Fy_x)),这个服务器就会解码的。
1 y: K4 L6 n  w; _$ R
5 _( P6 ?; X! P程序怎么改进呢?只要能够得到客户端提交的数据是解码后的就可以了,把得到name的语句改为For Each SubmitName In Request.QueryString就可以了。0 ^3 p) m3 I# H$ u  X4 [) I3 H
5 i" y. z1 P9 ^9 ]; X4 T! i
呵呵,谢谢阁下耐着性子看完我的文章^_^




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5