欢迎光临
我们一直在努力

跨过浏览器同源策略

0x01 前言

同源策略这玩意一直是玩web安全的朋友头疼的问题, 如今的浏览器沙盒对这方面的限制越来越严格,可利用的场景也愈加有限,但仍旧存在绕过同源策略一些tips。其实很早就想写这篇文章了,最近看到一些关于这方面的话题,刚好做一个总结。

0x02 同源策略简介

简单来说:同源策略就是域名、协议或端口不同的两个页面在未授权的情况下,无法读取对方的资源的一种安全策略。该策略最早由Netscape提出,如今所有支持javascript的浏览器都会支持该策略,已逐渐成为一个规范。

举个例子,现在有A和B两个网站,你登陆了A网站,浏览器存储了你的cookie信息,这时候,再访问B网站,B网站是肯定不能读取A存储在浏览器中的cookie的,这就是同源策略的作用,否则,整个基于身份验证的业务将一片混乱。

这里说到同源策略的限制主要在域名、协议和端口,在《web之困:现代web应用安全指南》一书中有比较详细的区分了,这里再写一下,我们以网站http://admin.heysec.org/test/test.php 为例,给出五种变形情况的读取资源情况:

QQ截图20160729145548 跨过浏览器同源策略

通过这个表格的展示,我们可以很清楚的看到同源策略的限制了,下面说说绕过同源策略的一些方法。

0x03 绕过方式

1.Document.domain跨域

这种跨域相对来说比较简单,就比如我们上面提到的两个同根域网站admin.heysec.org和login.heysec.org,若未经过任何设置,这二者之间是无法相互访问资源的,但如果我们在两网站根域设置document.domain=”heysec.org”,则heysec.org下所有的站点都可以访问DOM资源。

这样对于开发者而言是相当方便的,但同时也存在一个问题就是,一旦admin.heysec.org存在漏洞,如被植入恶意代码,那它就可以访问到login.heysec.org的资源,这是非常危险的,倘若一个站群被设置同样的domain,那么其安全性基本就依赖于防御最薄弱的那个子站点。

QQ截图20160729145548 跨过浏览器同源策略

2.PostMessage 跨域

Postmessage()是HTML5的一个新扩展,使用起来不如document.domain方便,但安全性却好很多,现在基本已被各大主流浏览器所支持。

这套机制由发送端来决定哪个页面能接收到发送出去的信息,在发送的过程中,也会为接收端提供发送页面自身的身份信息,所以能容易的确定通道的真实性。以往的一些依赖同源的做法并没有这样的保障,导致某些动作可能来自于恶意的第三方。

这里给出一个用例场景(引用自《web之困》),现在我们拥有一个后台分离的站群*.heysec.org。login.heysec.org是登录后台,index.heysec.org是前台页面,这时候我们需要在前台展示一些登录者的信息,那门我们就需要在index.heysec.org的页面中加载一个指向login.heysec.org的子框架,这个子框架只需要发送如下命令:

Parent.postMessage(“user=admin”,”http://index.heysec.com”);

当子框架的父级页面确认是指定的信任源时,浏览器才会向它发出postMessage的消息。而接收方则需要使用以下代码才能安全的处理这个响应:

//收到实际数据时的具体处理
Function user_info(msg){
    If(msg.origin==”http://login.heysec.org”){
//根据计划使用msg.data数据
    }
}

这种认证方式看起来很安全了,但安全的问题往往就出在人身上,倘若程序员在开发的时候,使用了不安全的代码判断,那这套机制也就不攻自破了:

If(msg.origin.indexOf(“login.heysec.org”)!=-1){……}

如果是以上代码,那我们构造login.heysec.org.evil.com即可成功绕过安全认证限制。

3.Window.name跨域

这个想必是大家了解的比较多的一种了,道哥在《白帽子讲web安全》书中就提到了这种跨域方式,这里解释一下原理,这种跨域方式的核心原理就是:

Window.name这个值很特别,当window的location改变时,并不会影响name的值

那么,我们就可以利用这个特性搞点事了,还是拿我们站点来举例子,index.heysec.org/cross.html和index.baidu.com/index.html想实现跨域资源访问,我们可以这样做:

  • 在index.baidu.org/cross.html设置window.name=document.cookie
  • 在index.heysec.org/cross.html建立iframe,地址指向index.baidu.org/cross.html
  • 设置onload响应事件,当iframe加载完成之后,利用js将其指向地址变为与index.heysec.org/cross.html同域下的一个地址(如index.heysec.org/test/index.html)
  • 读取此时的window.name,即可成功读取到index.baidu.org的cookie值

解释一下为什么要做第三步,其实也是由于同源策略的限制,否则是无法直接读取index.baidu.org/cross.html的name值的,这恰好就利用了我们前面说到的location改变而window.name不变的特性。

4.Jsonp跨域

记得在15年年初的时候,Jsonp劫持火了一把,当时我还专门写了一篇文章做了简单的分析,这里写的Jsonp跨域其实和Jsonp劫持用到的思想是一样的。

先解释下什么叫Jsonp,Jsonp就是通过动态创建<script>的方式来向不同域发送Http请求的一种方法,这里我们有两个页面A(a.heysec.org/index.php)和B(b.heysec.org/index.php),按我们之前的概念,这二者是不同域的。此时在A站点拥有callback函数,访问形式为http://a.heysec.org/index.php?calback=,此时我们想跨域获取A站点的资源,只需要在B站点加入如下代码

<script src=”http://a.heysec.org/index.php?callback=getInfo”></script>
<script>
    Function getInfo(info){
    //获取json数据并输出
    }
</script>

当我们访问B站点的时候,会自动加载A站点的callback函数,此时callback函数又会动态加载B站点的getInfo函数,使得该函数作为A站点自身的函数得以执行,从而获取到A站点的json数据,实现跨域。

5.特定浏览器跨域

由于当今的浏览器各玩各的,自身策略导致的跨域问题也很多,FB上专门有一篇文章介绍相关问题,写的很不错,大家要具体了解戳这里,我就不画蛇添足了。

0x04 结束

以上都是比较常规的跨域方式,当然,还有一些的插件导致的跨域,数量众多,无法一一阐述,想要更详细的了解可以参考权威文档。

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing

https://en.wikipedia.org/wiki/Same-origin_policy

https://www.w3.org/Security/wiki/Same_Origin_Policy

未经允许不得转载:杂术馆 » 跨过浏览器同源策略
分享到: 更多 (0)