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”。
解码软件
backspace %08 |
I %49 |
v %76 |
ó %D3 |
tab %09 |
J %4A |
w %77 |
Ô %D4 |
linefeed %0A |
K %4B |
x %78 |
Õ %D5 |
creturn %0D |
L %4C |
y %79 |
Ö %D6 |
space %20 |
M %4D |
z %7A |
Ø %D8 |
! %21 |
N %4E |
{ %7B |
ù %D9 |
" %22 |
O %4F |
| %7C |
ú %DA |
# %23 |
P %50 |
} %7D |
Û %DB |
$ %24 |
Q %51 |
~ %7E |
ü %DC |
% %25 |
R %52 |
¢ %A2 |
Y %DD |
& %26 |
S %53 |
£ %A3 |
T %DE |
' %27 |
T %54 |
¥ %A5 |
ß %DF |
( %28 |
U %55 |
| %A6 |
à %E0 |
) %29 |
V %56 |
§ %A7 |
á %E1 |
* %2A |
W %57 |
« %AB |
a %E2 |
+ %2B |
X %58 |
¬ %AC |
ã %E3 |
, %2C |
Y %59 |
ˉ %AD |
ä %E4 |
- %2D |
Z %5A |
o %B0 |
å %E5 |
. %2E |
[ %5B |
± %B1 |
æ %E6 |
/ %2F |
\ %5C |
a %B2 |
ç %E7 |
0 %30 |
] %5D |
, %B4 |
è %E8 |
1 %31 |
^ %5E |
μ %B5 |
é %E9 |
2 %32 |
_ %5F |
» %BB |
ê %EA |
3 %33 |
` %60 |
¼ %BC |
ë %EB |
4 %34 |
a %61 |
½ %BD |
ì %EC |
5 %35 |
b %62 |
¿ %BF |
í %ED |
6 %36 |
c %63 |
à %C0 |
î %EE |
7 %37 |
d %64 |
á %C1 |
ï %EF |
8 %38 |
e %65 |
 %C2 |
e %F0 |
9 %39 |
f %66 |
à %C3 |
ñ %F1 |
: %3A |
g %67 |
Ä %C4 |
ò %F2 |
; %3B |
h %68 |
Å %C5 |
ó %F3 |
< %3C |
i %69 |
Æ %C6 |
ô %F4 |
= %3D |
j %6A |
Ç %C7 |
õ %F5 |
> %3E |
k %6B |
è %C8 |
ö %F6 |
%3F |
l %6C |
é %C9 |
÷ %F7 |
@ %40 |
m %6D |
ê %CA |
ø %F8 |
A %41 |
n %6E |
Ë %CB |
ù %F9 |
B %42 |
o %6F |
ì %CC |
ú %FA |
C %43 |
p %70 |
í %CD |
û %FB |
D %44 |
q %71 |
Î %CE |
ü %FC |
E %45 |
r %72 |
Ï %CF |
y %FD |
F %46 |
s %73 |
D %D0 |
t %FE |
G %47 |
t %74 |
Ñ %D1 |
ÿ %FF |
H %48 |
u %75 |
ò %D2 |
|
URL编码平时是用不到的,因为IE会自动将输入到地址栏的非数字字母转换为url编码。曾有人提出数据库名字里带上“#”以防止被下载,因为IE遇到#就会忽略后面的字母。破解方法很简单——用url编码%23替换掉#。现在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里是否含有定义的关键字,有之,则为注射。
看起来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就可以了。
前言
编码问题是JAVA初学者在web开发过程中经常会遇到问题,其中之一是URL中使用中文等非ASCII的字符造成
服务器后台程序解析出现乱码的问题。
常见出错部分
也就是容易出现中文字符的部分:
(1)Query String中的参数值
(2)servlet path
常见出错原因
(1)浏览器:我们的客户端(浏览器)本身并没有遵循URI编码的规范。
(2)Servlet服务器:Servlet服务器的没有正确配置。
(3)开发人员并不了解Servlet的规范和API的含义。
servlet规范
(1)HttpServletRequest.setCharacterEncoding()方法 仅仅只适用于设置post提交的requestboda的编码而不是设置get方法提交的queryString的编码。该方法告诉应用服务器应该采用什么编码解析post传过来的内容。
(2) HttpServletRequest.getPathInfo()返回的结果是由Servlet服务器解码(decode)过的。
(3) HttpServletRequest.getRequestURI()返回的字符串没有被Servlet服务器decoded过。
(4) POST提交的数据是作为request body的一部分。
(5) 网页的Http头中ContentType("text/html; charset=GBK")的作用:
(a) 告诉浏览器网页中数据是什么编码;
(b) 表单提交时,通常浏览器会根据ContentType指定的charset对表单中的数据编码,然后发送给服务器的。
注意:这里所说的ContentType是指http头的ContentType,而不是在网页中mete中的ContentType。