同源策略与跨域

前言

下面总结的内容都比较简略,可能是摘抄了《白帽子》,可能是网上搜集的资料,或者直接给出了别人总结的很好的文章供以后查看,因为每个点展开来将都可以写好几篇文章(嗯,为自己偷懒找借口

什么是同源策略

源就是[主机,协议,端口名]的一个三元组。 (此外,cookie的同源策略是[主机,端口名],不包含协议,因此可以用http的cookie去覆盖https的cookie。)

同源策略(Same Origin Policy, SOP):限制了来自不同源的”document“或者脚本,对当前”document“读取或者设置某些属性。

<script>、<img>、<iframe>、<link>等标签都可以跨域加载资源,而不受同源策略的限制,但是浏览器限制了JS的权限,使其不能读、写返回的资源。

XMLHttpRequest不可以跨域加载资源,但是可以读写资源。如果可以跨域,则会导致一些敏感数据的泄漏,如CSRF Token。

XHR需要根据目标域返回的HTTP头来授权是否允许跨域访问,因为JS无法控制HTTP头(这点非常重要啊啊啊啊啊啊,👻👽💀🤖👏👏👏)。XSS在没有其他辅助的情况下也无法控制HTTP头啊啊啊啊。

除了DOM、Cookie、XHR受到同源策略的限制,第三方插件如Flash(crossdomain.xml、MIME)、Java、Applet等都有自己的同源策略。

跨域的方式主要有:

CORS
CSP
JSONP
postMessage

Cross-origin Resource Sharing(CORS)

例如从http://www.a.com/test.html发起对http://www.b.com/test.php的请求,请求头中包含origin:http://www.a.com

(origin header 可以用于防范CSRF,不像Refer那么容易被伪造或清空,此处的referer怎么改?????😱😱😱😱😱😱😱😱😱😱😱)

如果www.b.com返回的http Header中包含:Access control allow origin:http://www.a.com,则表示这个跨域请求被通过。(下图是图糙理不糙啊啊啊

还有很多其他的标准:

Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age

Content Security Policy(CSP)

由服务器返回一个HTTP头,并在其中描述页面该遵守的安全策略。

X-Content-Security-Policy:allow 'self' *.mydomain.com    // 浏览器将信任来自mydomain.com及其子域名下面的内容

CSP的实质为白名单,在浏览器层面做的防护,是和同源策略同一级别,除非浏览器本身出现漏洞,否则不可能从机制上绕过。 CSP只允许被认可的JS块、JS文件、CSS等解析,只允许向指定的域发起请求。

CSP怎么能有这么多姿势…

JSONP(只支持get请求)

JSONP(JSON with Padding)是一个简单高效的跨域方式,可以简单理解为带callback的json。利用<script>标签没有跨域限制的“漏洞”(历史遗迹啊)来达到与第三方通讯的目的。 参考知乎

当需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如:

    <script src="http://www.example.net/api?param1=1&param2=2"></script>

并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。     

第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:     

    callback({"name":"hax","gender":"Male"})     

这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。

JSONP是CSP的克星

<script src="/path/jsonp?callback=alert(document.domain)//"> </script>

postMessage

postMessage允许每一个window(包括当前窗口、弹出窗口、iframe等)对象往其他的窗口发送文本消息,从而实现跨窗口的消息传递,不受同源策略限制。

同源攻防

漫谈同源策略攻防

  • 对URI的解析:

    在某些浏览器对URI的解释存在漏洞的时候,可以构造相应的攻击连绕过SOP

  • 设计缺陷绕过SOP:

    在Java6,7中,如果两个域名解析到相同的IP,则会认为他们同源。假设我们有attacker.com和victim.com,两者都共享主机123.123.123.123。攻击者attacker.com可以在自己控制的域名下上传一个jar文件来访问victim.com的内容。

  • 访问本地文件的同源策略

    <frame src="/home/user/dir/2.html">

    <frame src="/home/user/2.html">

    1.html与2.html视为同源

  • 特立独行的IE:

    TrustZones(信任域):当一个URI被加入到了IE的信任网站区域中时,浏览器会无视同源策略。

    IE在考虑同源策略时不包括端口, 这意味着不同端口上的应用程序可以读取到比如用户的登陆账户密码/cookie等。

    通过变更自身的源绕过同源策略:IE 6,7版中网页可以通过document.domain设置自身的来源为任意其他来源

防御

最好的防御方式则是设置CORS

禁止跨域写,引入CSRF令牌,且必须正确的配置同源策略,否则令牌也会被读取。

禁止跨域读,我们可以通过设置X-Frame-Options头来禁止该页面被嵌入到恶意页面中

禁止跨域嵌入,比如<script data-original=></script><img data-original=x></img><svg onload=>,各种字体加载等等。同时,使用CSRF令牌也可以有效避免被跨域嵌入。