(注:阅读本文需要读者对CSRF等一些常见WEB攻击有所了解)
如今的WEB标准纷繁复杂,稍大一些的网站内容早已不仅限于网站自身提供的内容,而是来自一堆五花八门的网站的内容的集合。 同源策略被广泛地应用在处理WEB内容的各种客户端上,比如各大浏览器,微软的Silverlight,Adobe的Flash/Acrobat等等。
深入了解同源策略是十分有必要的,在攻击上,要深入掌握XSS / CSRF等WEB安全漏洞,不了解同源策略就如同盲人摸象一般,无法说出全貌,更无法应用其进行打击。在防御中,理解了同源策略,就有助于理解自己面临着什么样的威胁,无论是网银盗号,还是隐私泄露。
源就是主机,协议,端口名的一个三元组。
同源策略(Same Origin Policy, SOP)是Web应用程序的一种安全模型,重要的事情说三遍,它只是个模型,而不是标准(哪怕标准在实现的时候也会千差万别)。
定义:给定一个页面,如果另一个页面使用的协议、端口、主机名都相同,我们则认为两个页面具有相同的源。 举个例子,我们假设需要比对的目标页面来自这个URI: http://sub.eth.space/level/flower.html
首先,我们要明确同源策略只 作用在实现了同源策略的WEB客户端 上。 虽然笔者不常用百度,但是我们来看一个具有误导性的结论:百度词条对于同源策略的解释说“只有和目标同源的脚本才会被执行”,这是不对的,同源策略没有禁止脚本的执行,而是 禁止读取HTTP回复 。 更正了这个概念之后,我们会发现,SOP其实在防止CSRF上作用非常有限,CSRF的请求往往在发送出去的那一瞬间就已经达到了攻击的目的,比如发送了一段敏感数据,或请求了一个具体的功能,是否能读取回复并不那么重要(唯一的作用是可以防止CSRF请求读取异源的授权Token)。 另外,一般 静态资源通常不受同源策略限制 ,如js/css/jpg/png等。
作为一个WEB安全模型,它被各大浏览器分别实现,这就带来了许多差异点,正所谓“千里之堤,溃于蚁穴”。
不同的浏览器使用不同的浏览器引擎,而不同的引擎对于同源策略的处理也并非完全一致。例如,Firefox使用Gecko浏览器引擎,在古老的Gecko1.8版(Firefox3)之前,任意两个file://的URI都被认为是同源的,意思就是,任意本地HTML文件将有权限访问本地计算机上任意其他文件。如今的Gecko版本中,一个HTML文档只能访问其所在文件夹下的其他文件。 SOP影响范围包括:普通的请求、XMLHttpRequest、XSLT、XBL。
对于跨越窗口的DOM访问,每个文件被当作一个单独的源,除了一种情况:当一个文件被另一个文件可以用同源策略访问时,视为相同的源。
<!-- 文件路径:/home/user/1.html --> <html> <frameset cols="50%,*"> <frame src="/home/user/dir/2.html"> <frame src="..."> </frameset> </html>
上图中,1.html和2.html被视为相同的源。
<!-- 文件路径:/home/user/dir/1.html --> <html> <frameset cols="50%,*"> <frame src="/home/user/2.html"> <frame src="..."> </frameset> </html>
上图中,1.html和2.html被视为异源。
在IE中,有两种情况同源策略 无效 :
例如 http://malicious.eth.space/1.html
可以通过执行
document.domain = "eth.space";
来绕过同源策略的限制,从而可以读取 http://eth.space/login.html
上的内容。这其中的应用大家可以自己去想。
由于运行以下js代码
document.domain = document.domain
将会导致端口号被重置为null。所以源 http://eth.space:1337
不能通过修改 document.domain="eth.space"
来访问 http://eth.space
的数据,除非后者也设置了 document.domain="eth.space"
,这样双方的源端口号才能一致( null
)。反之亦然。
为什么要起这么拗口的名字:网络访问?因为WEB上资源访问的多样性,不能简单的称之为网络请求。大体看来我们有三种类型:
早在2011年,一个用户在Mozilla的Bug追踪系统中就提交了一个issue,声称他可以判定某个网站的访客是否登录了gmail,facebook等等。
嵌入iframe来获取一个访问网站的用户是否登陆了gmail:
<img style="display:none;" onload="logged_in_to_gmail()" onerror="not_logged_in_to_gmail()" src="https://mail.google.com/mail/photos/img/photos/public/AIbEiAIAAABDCKa_hYq24u2WUyILdmNhcmRfcGhvdG8qKDI1ODFkOGViM2I5ZjUwZmZlYjE3MzQ2YmQyMjAzMjFlZTU3NjEzOTYwAZwSCm_MMUDjh599IgoA2muEmEZD" />
src的代码试图访问一张gmail中攻击者上传的图片,如果用户没有登陆gmail,就无法成功加载。从而达到判断用户是否登陆gmail的效果。这种方法可以 推广到任何对不应跨源访问的资源没有正确设置同源策略的网站 。
如何安全地允许跨源访问?
<script src=></script>
<img src=x></img>
, <svg onload=>
,各种字体加载等等。同时,使用CSRF令牌也可以有效避免被跨域嵌入。 如何禁止你控制的网页中嵌入的iFrame做出恶意行为?
使用HTML5的沙盒iframe。
先说到这里吧,关于跨域资源共享CORS下次再写。
ps. 转载请注明出处.