论坛首页 AJAX版 AJAX

绕过浏览器相同来源策略的一些方法

浏览 866 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-12-21
浏览器的相同来源策略大家都很清楚。它在保证了用户安全性的同时,也为实现某些类型的Ajax应用造成了很大困难。经常有人尝试用各种方法来绕过相同来源策略,但是很少有人成功。相同来源策略是W3C所规定的一个严格的限制机制,如果能够轻易绕过,那将是这个浏览器版本的重大安全漏洞。

我来总结一下我至今见到过的绕过相同来源策略的几种方法。

1. 通过同一个服务器请求来自不同来源服务器的页面。
在客户端,需要对XMLHttpRequest对象做一下封装。就是以GoF的Decorator模式对XMLHttpRequest对象做封装,得到一个接口完全相同的新对象。这个新对象可以接受对不同来源服务器的请求(XMLHttpRequest对象本身是不接受的),如果发现是对不同来源服务器的请求,在这个新对象的内部将URL转为相同来源服务器上的某个镜象URL。
在服务器端,识别出对不同来源服务器的请求,得到其真实URL,获取其内容返回给客户端。服务器端实现的是一个GoF的Proxy模式。

2. 实现一个HTTP代理服务器,将浏览器设置为使用这个HTTP代理服务器。
客户端和HTTP代理服务器要做的事情和方法1完全相同。
这是Selenium RC所采用的方法。它为了测试任意来源服务器页面中的脚本,运行时自动将自己设置为IE或Firefox的HTTP代理服务器,将一些页面(及其所包含的测试脚本)插入到被测试页面的来源服务器的URL空间,使得浏览器误以为这些测试脚本与被测试页面属于相同的来源服务器。

3. 如果不同的来源服务器提供的是JSON格式的数据,那情况就简单多了。
动态创建一个script标签,将其src属性指向这个URL就可以了。浏览器获取这些JSON数据,立即对其执行eval。你无法做其他什么事情,因为你无法控制这个过程。
这也是以JSON格式暴露出Web服务越来越流行的原因。因为这种方式非常便于客户端脚本集成来自多个数据源的数据。Yahoo!的论坛暴露出的数据就是JSON格式的。

注意:使用这种方法是非常危险的!除非你仔细检查过获取到的JSON数据的内容,确保这些内容没有做任何危害用户的事情;或者你100%信任Yahoo!的服务器管理员,因为他正是你的亲兄弟。否则用户受到的任何恶意攻击,他们都会迁怒于你,你会很快成为众矢之的,甚至会遭到法律诉讼。

4. 使用一个IFrame,父页面的脚本可以修改子页面(就是那个IFrame)URL中#后的内容,子页面也可以修改父页面URL中#后的内容。
这样你在子页面中就可以设置一个onload函数,加载完后通过修改父页面URL中#后的内容,将一些信息传递给父页面。父页面中使用一个周期运行的轮询函数,从自己的URL中取出这些信息。
Dojo里面使用这个技术实现了一种来自不同来源服务器的页面之间的通信机制。

不过这种方法局限性很大:
首先,要给IFrame所加载的页面加onload函数,你必须对这个页面所在的服务器有控制权。否则你就只能试图以木马攻克这个网站,或者行贿这个网站的服务器管理员。
其次,在URL中#后面能够传输的数据量非常少。如果数据量很大,必须要以多次搬运和组装的方式来实现,那样将是非常低效的。

应该还有更多的方法,不过这些方法都有局限,不是那么容易实现的。大家如果感兴趣,可以用电骡去搜索:
XSS Exploits: Cross Site Scripting Attacks and Defense
这本书。这是一本关于这个特定领域非常有趣的书。
   
最后更新时间:2007-12-22
dlee老大遗忘了跨域XHR,firefox 3.0正式支持http header验证跨域XHR了,我在javaeye有文章介绍的
   
0 请登录后投票
最后更新时间:2007-12-22
那是很新的东西了,Firefox 3.0正式版目前还没有推出,我确实不了解。

Firefox实现这个功能也是因为确实需要有一种方法,既能够保护用户的安全和隐私,也能够帮助客户端脚本集成来自不同来源服务器的数据。Mashups一类应用的流行提出了很多这方面的需求。难的是如何将两方面都兼顾好。

不过还是希望最后由W3C提出这样一种方法,得到IE、Firefox等所有主流浏览器的承认。否则他们各自为战,苦的还是应用的开发人员(为IE开发一套代码,为Firefox开发另一套代码)。

目前还有很多标准化的工作需要W3C、ECMA和IETF等组织尽快完成:
1. 集成来自不同来源服务器的数据的标准。
2. 客户端本地存储的标准。
3. JavaScript 2.0的标准。
4. HTML 5.0的标准。

一年之内如果这些标准化的工作都能完成那最好了,否则新的浏览器大战还是有可能会出现。出于稳妥起见,我们做产品或项目时还是只能使用这些浏览器之间的最大公约数。
   
0 请登录后投票
最后更新时间:2007-12-22
dlee大哥误会了,其实就是W3C制定的cross-sites request处理办法,文档在这里http://www.w3.org/TR/access-control/
1. 集成来自不同来源服务器的数据的标准。
2. 客户端本地存储的标准。
3. JavaScript 2.0的标准。
4. HTML 5.0的标准。
1已经有了,但是目前还是草案,估计ie8实现可能不大
2.目前userdata和storage(ff)可以用,但是标准还没有,当然flash也能存
3.ecma v4是很火,但是没吗用,需要大规模js编码可能会有些帮助,高性能可能也会有些帮助
4.哪个东西可以减少一点编码,可能引入新的标签,但是实现速度如何,很不好说,我还是觉得先把video tag都实现了比较现实
   
0 请登录后投票
最后更新时间:2007-12-22
dlee 写道

3. 如果不同的来源服务器提供的是JSON格式的数据,那情况就简单多了。
动态创建一个script标签,将其src属性指向这个URL就可以了。浏览器获取这些JSON数据,立即对其执行eval。你无法做其他什么事情,因为你无法控制这个过程。
这也是以JSON格式暴露出Web服务越来越流行的原因。因为这种方式非常便于客户端脚本集成来自多个数据源的数据。Yahoo!的论坛暴露出的数据就是JSON格式的。

注意:使用这种方法是非常危险的!除非你仔细检查过获取到的JSON数据的内容,确保这些内容没有做任何危害用户的事情;或者你100%信任Yahoo!的服务器管理员,因为他正是你的亲兄弟。否则用户受到的任何恶意攻击,他们都会迁怒于你,你会很快成为众矢之的,甚至会遭到法律诉讼。

动态创建script标签不一定需要来源服务器提供JSON格式数据,来源服务器用XML,甚至是HTML你也可以解析以后进行处理,JSON只是方便一些而已。
有一个基于PrototypeJS的插件:
http://www.mellowmorning.com/2007/10/25/introducing-a-cross-site-ajax-plugin-for-prototype/
用来作CrossSite的Ajax应用非常简便
   
0 请登录后投票
最后更新时间:2007-12-23
to Readonly:
这个方法看来确实是最简单的方法。以前难以实现是因为浏览器的script标签并不支持onload之类的回调,当然也不支持readyState。浏览器现在仍然不支持,所以需要自己做一些hack。

这个作者的做法是采用一个轮询函数来检查:
Detecting the loading of a script element is not that easy. Browsers such as Safari and Konqueror simply give no indication of this at all. One common solution to dealing with this is to use an interval and perform a check.

检查完script标签加载成功之后做些什么事情呢?
另外一个难度正在这里,作者的文章语焉不详,其实这里面存在着大量的hack。

我的猜测是:
得到script标签的DOM对象,执行其toString(或者toSource?),然后对得到的内容做解析。
不过script标签无论是静态在页面中的,还是动态创建的;无论是已经append到DOM树的,还是没有append到DOM树的,当它加载到非法的JSON数据时都会报错的。如果它是动态创建的,而且还没有append到DOM树上,这个错误就不会报告给用户?

这种方式对于内容的格式应该还是有很多限制的,我不是很确信它能支持任意的文本格式。
Readonly可以做一个例子来证实一下,然后我们再做深入的讨论。

如果它能支持任意的文本格式,那将对浏览器相同来源策略造成重大隐患,浏览器的开发者又要忙了。
所以最终的解决方案还是使用W3C新定义的那个模型。
   
0 请登录后投票
最后更新时间:2007-12-23
方法3,即动态创建script标签,这种方法为何是非常危险的呢?

script标签可以接受的内容可以是任意合法的JavaScript代码,不只是合法的JSON,而且你无法阻止浏览器自动执行获取到的内容。等你要做什么事情的时候,这些代码已经执行完了,执行这些代码的效果已经无法挽回了。

假设我使用了Yahoo!的JSON数据,他们的管理员有一天在这些数据中加入了一些代码,这些代码做了一件我没有想到的事情:
1. 因为这些代码是与本来源服务器绑定的,所以它可以获取本来源服务器所设置的所有cookie,还可以遍历浏览器的history对象,以发现它所感兴趣的内容。假设它发现了在cookie中保存的username和password。
2. 这些代码动态创建了一个iframe标签,或者创建了一个script标签,指向某个URL,然后将username和password作为参数附加在URL后面。
3. 动态创建的iframe或script标签自动发送一个HTTP请求,该请求的目的服务器获取到了用户的username和password。

因为没有将动态创建的iframe或script标签append到DOM树,所以所有这一切都是在后台静悄悄地执行的,UI没有任何变化,用户根本不知道发生了什么。
这还只是最简单的情况。动态脚本可以创建新的动态脚本,新的动态脚本还可以再创建新的动态脚本。动态脚本威力巨大,威胁也是巨大的。只要有足够的想象力,这些动态脚本可以做的事情是无限的。
   
0 请登录后投票
最后更新时间:2007-12-26
疑问:为什么Douglas Crockford 说JSON是安全的?

引用
JSON is a data interchange format. It is used in the transmission of data between machines. Since it carries only data, it is security-neutral. The security of systems that use JSON is determined by the quality of the design of those systems. JSON itself introduces no vulnerabilities.


引用
JSON是一种数据交换格式,可用于机器之间的数据传送。它只是表达数据,所以它本身是与安全无关的。使用JSON的系统安全与否,取决于该系统自身设计的好坏。JSON本身并不会引入安全隐患。


《JSON and Browser Security》
April 10, 2007 at 10:14 am by Douglas Crockford | In Development |
http://yuiblog.com/blog/2007/04/10/json-and-browser-security
   
0 请登录后投票
最后更新时间:2007-12-26
Douglas说的与前面讨论的内容并不矛盾。

前面所讨论的其实是任意合法的JavaScript代码,JSON数据也是合法的JavaScript代码。反之则不然,并非任意合法的JavaScript代码都是合法的JSON数据。JSON数据格式的定义在这里:
http://json.org/json-zh.html

来自第三方的JavaScript代码如果不加控制地自动执行,会对于用户的安全和隐私造成很大威胁。使用动态创建的script标签正是这样一种情况。这些代码是否应该执行、在何时执行、是全部执行还是有选择地部分执行,都是客户端脚本无法控制的。
   
0 请登录后投票
论坛首页 AJAX版 AJAX

跳转论坛:
JavaEye推荐