在HTML 4的History API中包含一个属性和三个方法。
HTML5的History API中新增加了两个新方法pushState()和replaceState()。这两个方法可以在不刷新页面的情况下添加和修改历史条目。
pushState()的格式如下:
pushState(data, title [, url])
pushState()的作用是在浏览器历史列表的栈顶部添加一条记录。它需要三个参数,一个是状态对象,一个是标题(这个目前被忽略),一个是URL(可选,同域)。
replacdState()的格式如下:
replaceState(data, title [, url])
replaceState()的作用是更改当前页面的历史记录。其参数和pushState()相同。
短地址服务是指把一个冗长的网址转换成一个简洁的网址。随着Twitter等微博的兴起,短地址服务也渐渐流行起来。现在国内的微博中,都会使用短地址服务,毕竟一条微博只能输入140个字,短地址服务大大压缩了网址所占的空间。
使用bit.ly短地址服务可进行网址转换,如表8-1所示。
表8-1 短地址转换
原网址 | http://hi.baidu.com/xisigr/blog/item/cb6aecc9a61ee10a7e3e6f32.html |
转换后的网址 | http://bit.ly/rFNVDw |
不难发现,当用户单击短地址的时候,并不知道它指向哪里,此时攻击者就可以利用短地址这个特性,把注入恶意代码的网站转换为短地址,用户单击这个短地址后,就会遭到攻击。
例如,表8-2中的这个短地址转换,在恶意URL网址中,appid参数后面就是我们注入的跨站测试代码。为了隐藏URL中的跨站代码,可以使用短地址服务http://bit.ly/将其转换为短地址,转换后的短地址为http://bit.ly/qxJuSF。此时转换后的短地址已经看不出来是一个恶意网址了。
表8-2 恶意短地址转换
恶意URL网址 | http://mail.test.com/?userid=&appid=<script>document.write(1)</script> |
转换后的网址 | http://bit.ly/qxJuSF |
此时,你也许会认为这样的隐藏太完美了。其实它也存在不足,当用户单击http://bit.ly/qxJuSF后,在浏览器的URL地址栏中仍会呈现http://mail.test.com/?userid=&appid=<script> document. write(1)</script>地址。只能说使用短地址服务隐藏恶意代码只隐藏了一半,用户始终可以看到注入的恶意代码。
接下来使用History的新方法来隐藏另一半,让恶意代码执行后,用户无法看到URL中的恶意代码。要说明的是,修改后的URL必须和当前的URL同域,这里把URL参数的位置写成location.href.split("?").shift()。
短地址转换前后如表8-3或表8-4所示。
表8-3 恶意短地址转换隐藏技巧1
恶意URL网址 | http://mail.test.com/?userid=&appid=<script>history.pushState({},'', location.href.split("?").shift());document.write(1)</script> |
转换后的网址 | http://bit.ly/uYAqsC |
表8-4 恶意短地址转换隐藏技巧2
恶意URL网址 | http://mail.test.com/?userid=&appid=<script>history.replaceState({},'', location.href.split("?").shift());document.write(1)</script> |
转换后的网址 | http://bit.ly/tKJvnY |
当用户单击短地址链接后,看到浏览器中的URL将会被替换为http://www.mail.test.com/。参数appid后面的跨站代码document.write(1)此时也已经执行。
通过上面的分析知道,传统方式下隐藏URL中的恶意代码可以使用短地址服务。但这样隐藏后,当用户单击执行时,还是会在浏览器URL地址栏中看到恶意代码。现在可以利用History的新方法pushState()和replaceState(),在无刷新页面的情况下改变地址栏中的URL,用户就无法看到恶意代码。所以,通过以上两种方法的结合,可以完美地隐藏URL中的恶意代码。
在Chrome浏览器中打开以下脚本程序:
<script> for(i=0;i<=100;i++){history.pushState({},"","/"+i+".html"); </script>
然后在Chrome浏览器中查看历史记录,可以看到有很多历史记录信息,如图8-1所示,而这些链接信息用户其实根本没有访问过。
图8-1 Chrome下伪造历史记录
通过这个例子我们可以看到,使用history.pushState可以对浏览器的历史记录进行伪造,而且也可以对历史记录发起DoS攻击。