美文网首页笔戈 Web Team让前端飞知曰
同源策略——浏览器的安全卫士

同源策略——浏览器的安全卫士

作者: 流星狂飙 | 来源:发表于2014-10-26 12:45 被阅读2781次

    对于软件开发者来说,理解同源策略,可以很好地解决了一个痛点,** 不同域名下的资源读写 !**

    古代的楚河汉界明确地规定了双方的活动界限,如果没有这些界限,天下必将大乱。同样,在我们的浏览器,也有着一些界限和策略,才让 Web 世界之所以能如此美好地呈现在我们面前,这些安全策略有效地保障了用户计算机的本地安全与Web安全。

    同源策略

    浏览器有一个很重要的概念——同源策略(Same-Origin Policy)。所谓同源是指,域名,协议,端口相同。不同源的客户端脚(javascript、ActionScript)本在没明确授权的情况下,不能读写对方的资源。

    同源策略,它是由 Netscape 提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。
    实际上,这种策略只是一个规范,并不是强制要求,各大厂商的浏览器只是针对同源策略的一种实现。它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之的。

    如果Web世界没有同源策略,当你登录Gmail邮箱并打开另一个站点时,这个站点上的JavaScript就可以跨域读取你的Gmail邮箱数据,这样整个Web世界就无隐私可言了。

    ** cookie 劫持 **浏览器中的 cookie就变得非常不安全,a 域名下的网页,就可以读取你浏览器中的所有 cookie,如果攻击者能获取到用户登陆凭证的Cookie,甚至可以绕开登陆流程,直接设置这个cookie的值,来访问用户的账号。

    举例说明

    安全防御

    客户端的攻击主要来自javascript的脚本,一般体现在对未授权的资源进行读写操作

    Web上的资源有很多,有的只有读权限,有的同时拥有读和写的权限。比如:HTTP请求头里的Referer(表示请求来源)只可读,同源和不同源就是根据这个Referer值进行判断的, 而document.cookie则具备读写权限。这样的区分也是为了安全上的考虑。

    跨域请求

    比如:在 a 页面使用 AJAX 发送一个请求,请求的地址是另外一个站点,
    注:
    AJAX是Asynchronous JavaScript And XML的缩写,让数据在后台进行异步传输,常见的使用场景有:对网页的局部数据进行更新时,不需要刷新整个网页,以节省带宽资源。AJAX也是黑客进行Web客户端攻击常用的技术,因为这样攻击就可以悄无声息地在浏览器后台进行,做到“杀人无形”。

    点击查看响应数据:手机归属地 API
    如果使用 ajax 发送请求,像下面这样

    $.ajax('http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443');
    

    响应数据,oop 报错了

    XMLHttpRequest cannot load http://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel=15850781443. 
    No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.baidu.com' is therefore not allowed access. 
    

    因为不同源,浏览器把这个操作给拦截了,然后返回一个错误给用户。

    解决办法

    目标站点,假如是http://tcc.taobao.com明确返回HTTP响应头:

    Access-Control-Allow-Origin: http://www.evil.com   
    

    或者设置为 *, 允许所有网站进行同源访问,但是这样也太不安全了。

    用 jsonp 来解决跨域问题

    JSONP(JSON with Padding)是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)。

    举个例子

    ** 客户端 **
    在客户端调用提供JSONP支持的URL Service,获取JSONP格式数据。
    比如客户想访问http://www.yiwuku.com/myService?jsonp=onCustomerLoaded
    假设客户期望返回JSON数据:["customername1","customername2"]
    那么真正返回到客户端的 数数据:

    callbackFunction([“customername1","customername2"])
    
    <script type="text/javascript">
          function onCustomerLoaded(result, methodName){
              conssole.log(result);//  输出结果 ["customername1","customername2"]
          }
    </script>
    <script type="text/javascript" src="http://www.yiwuku.com/myService?jsonp=onCustomerLoaded"></script>
    

    服务器端:

    String callback = request.getParameter("callback");
    out.println(callback + "('" + data+ "')");
    

    或者使用 jquery 的ajax 解决方案

    $.ajax({   
      url: 'http://localhost:8080/test2/searchJSONResult.action',  
      type: "GET",   
      dataType: 'jsonp',   
      data: {name:”ZhangHuihua”}, timeout: 5000,   
      success: function (json) {  
        //客户端jquery预先定义好的callback函数,成功获取跨域服务器上的json数据后,会动态执行这个callback函数   
        alert(json);   
      },   
      error: function (){  
        alert("请求失败!");   
       }  
    });
    

    HTML中的script标签可以加载并执行其他域的JavaScript,于是我们可以通过script标记来动态加载其他域的资源。JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行,那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。

    jsonp 带来的问题

    JSONP为解决跨站问题带来便利的同时,也存在一定的潜在风险,下面以实例说明其风险。比如jsonpTest.htm提供jsonp格式的调用,返回如下面格式的callBack({"json":"jsonTest"})的数据。

    • 脚本注入
      未对回调的函数名以及输入内容进行过两次。比如用户输入如下面请求:
      xxx.com/jsonpTest.htm?jsonp=alert('OK');
      则若服务器不过滤,响应内容为alert("OK");{"json":"jsonTest"}
      如果 jsonp 请求为:
    xxx.com/jsonpTest.htm?jsonp=<img onclick=”xxx”/>
    

    则若服务器不过滤,响应内容为:
    <img onclick=”xxx”/>;{xx}
    用户点击图片,也会有xss攻击。

    • 恶意攻击
      对输入的内容进行安全转义过滤,却未限定jsonp回调的合法的字符,下面参数经过安全转义后仍然不变。while(true){alert(document.cookie)} 攻击者就可以使用此参数对用户进行恶搞。
    • 解决办法
      • 对输出的内容进行必要的安全转义
      • 限定jsonp的回调方法名的安全字符范围为(a-zA-Z0-9$ )
      • 设置响应类型是非json或javascript类型,比如text/html。防止攻击者直接输入jsonp请求的url,浏览器端收到数据时以js的方式运行响应的内容。

    跨域的更多解决办法

    • 如果是log之类的简单单项通信,新建<img>,<script>,<link>,<iframe>元素,通过src,href属性设置为目标url。实现跨域请求
    • 现代浏览器中多窗口通信使用HTML5规范的 targetWindow.postMessage(data, origin);,其中data是需要发送的对象,origin是目标窗口的origin。window.addEventListener('message', handler, false);handler的event.data是postMessage发送来的数据,event.origin是发送窗口的origin,event.source是发送消息的窗口引用
    • 内部服务器代理请求跨域url,然后返回数据
    • 跨域请求数据,现代浏览器可使用HTML5规范的CORS功能,只要目标服务器返回HTTP头部Access-Control-Allow-Origin: 即可像普通ajax一样访问跨域资源

    参考文献:

    相关文章

      网友评论

      • 百步半九十:楼主 你好我想请教下,
        “当你登录Gmail邮箱并打开另一个站点时,这个站点上的JavaScript就可以跨域读取你的Gmail邮箱数据“
        如果没有跨域,a页面的js就可以操作b页面吗? 我只知道通过iframe可以获取dom之类的,不是ifame也可以吗
      • 31b12f14a4c6:alert("OK");{"json":"jsonTest"}

        为什么不是

        alert("OK");({"json":"jsonTest"})
      • 流星狂飙:@The_Fancy 你可以查下 XSS 是什么
      • d19b7f381b47:jsonp 带来的问题 这里有疑惑:

        <img onclick=”xxx”/>;{xx}

        服务器返回的东西应该是到了客户端A 去了,那么此时跟服务器应该没关系才对?
      • 阿树:开头的比喻略屌。
      • 流星狂飙:软件开发 技术贴

      本文标题:同源策略——浏览器的安全卫士

      本文链接:https://www.haomeiwen.com/subject/uhhvtttx.html