URL是如何解析的
URL就是我们天天使用的网址,英文全称叫做uniform resource locator,你可以把它理解成互联网上每个页面独一无二的名字.其实也不全是页面了,比如一些FTP下载资源,或者网页上的mailto链接,都是使用URL表示的.其实URL就相当于互联网字典上的索引,这些URL本来是一个个的孤岛,被一些资源整合的工具(比如搜索引擎)整合后,使得互联网得以连接,所有的links加起来,就是我们看到的互联网了.关于URL的解析其实也是一个很复杂而又麻烦的事情,可不像我们打开浏览器输入baidu.com然后回车得到一个输入框那么轻松.
那么它到底复杂到哪了,我们慢慢了解吧...
关于URL的语法一般是这样的:
scheme://[login[:password]@](host_name|host_address)[:port][/hierarchical/path/to/resource[?search_string][#fragment_id]]
我们一个一个看:
scheme可不是那个满屏幕小括号的编程语言,而是方案的意思,其实我认为可以理解成打开一个互联网资源的方式,比如http和ftp就是不同的方式,常用的scheme包括http,https,ftp,mailto,javascript,file(一般是打开本地浏览器可以打开的资源时使用的),chrome(Chrome浏览器特有的).scheme名称后加一个冒号,标准写法是在':'前只能出现[a-z][A-Z][0-1]+-.这些字符的,但是很多浏览器对于额外的字符也能够解释,比如下面这样的HTML代码,对于Chrome也是可以解析的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>scheme</title> </head> <body> <a href="http: www.baidu.com">baidu</a> <a href="javascript	:alert(1);">javascript alert()</a> </body> </html>
	在HTML中是TAB的转移字符,可以在free-formatter中转义回来.
不过对于Firefox第二个弹窗代码就没法使用了,它解释成了file:///Users/zookeep/Desktop/web/javascript:alert%281%29;一个本地文件的相对路径地址.
对于Safarier,会把第一个URL解释成http:%0A%0A//www.baidu.com其中的换行符变成了line feed就无法打开百度了.
对于scheme,我们试试file一个本地可执行文件hello.exe,发现它没法执行文件而是把它下载下来了,看来file方法只能打开浏览器可以识别的格式的文件,比如html,PDF等。
然后就是两个//,如果不写的话又会怎样:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>without //</title> </head> <body> <a href="http:baidu.com">baidu</a> <a href="./http:baidu.com">baidu</a> </body> </html>
第一个没有指定目录,会被解释成和http://baidu.com一样的URL,而加上./(表示当前目录),则会被解释成一个本地的目录.
下面是[login[:password]@]用户的认证信息,这个其实现在用处不大,几乎没人会让用户这样验证,都是表单验证了.不过这个认证信息选项会让一些URL看起来很猥琐,我们以后再看.
接下来是主机名或者主机IP地址,比如localhost,或者一个域名google.com或者一个IP:http://74.125.130.99(同样是Google).不过这些常规的写法大家都明白,那么一些猥琐的写法可以
是这样的:
http://0x7f.1
http://017700000001
同样都是localhost的表示,第一个是把点分十进制第一个127写成16进制,其他三个组成一个数字,第二个是把127.0.0.1每一个十进制都转为8进制然后加个0表示八进制的IP.
对于Google地址 74.125.130.99我们也可以这样写:
>>> a = '74.125.130.99' >>> map(hex, map(int, a.split('.'))) ['0x4a', '0x7d', '0x82', '0x63'] >>> '.'.join(map(hex, map(int, a.split('.')))) '0x4a.0x7d.0x82.0x63'
同样可以得到Google的页面.
或者:
>>> '.'.join(map(oct, map(int, a.split('.')))) '0112.0175.0202.0143'
也可以访问到Google.
对于端口号倒是没什么可以玩的,记住常用的http是80, https 是443就行了.
下一个是路径和资源比如/home/user/index.html这样的文件,不过现在很多都不显示文件的后缀了,因为都是动态网站了...
下一个是查询字符串,这个就很有用了,比如使用taobao的时候你输入的查询内容就会被填充到query中,
比如taobao.com/search?q=html就能在taobao找到你要的宝贝了...
下一个是片段ID,这个可是个好东西,不过注意它和服务器可是没有交互的,只是会在当前页面找到一片内容,由浏览器跳到那里去,
更多的内容可以参考 这里.
好了,我们基本上看完了URL的基本解析方式,那么如下的URL到底会把你带到哪里:
http://qq.com&location=12306.com@evil.net http://a@b@c.com http://www.sina.com&id=123@0300.0250.01.01
ok,看第一个,这不就是qq嘛,好了,你把它输入Chrome一看,跑到了evil.net什么鸟玩意.
第二个,也许会是a@b@c.com,进去看看再说,不过伟大的Chrome把我们带到了c.com
第三个,估计是sina网吧...好吧,它把我带到了我的路由器登录页上.这是什么乱七八糟的?!
其实,URL的解释是没错的,不过我们忽视了登录信息罢了,[login[:password]@]
第一个URL中,qq.com&location=12306都被当做了你访问evil.net的用户名了
同样的a@b也被当成c.com的认证消息了,
第三个也是一样,只不过把域名换成了一个IP地址,更加难以看出真实的hosts是谁.如果再用HTML转义以下,估计就没人能看清楚了,哈哈...
不过我发现,万能的Chrome还是可以在你的地址栏中高亮出真实的网址:
只是一般情况下大家都没有注意到罢了.
好了,这个令人头疼的URL解析算是差不多搞明白了.
参考: https://code.google.com/p/browsersec/wiki/Part1