为什么同源政策如此重要?

信息安全 Web应用程序 网页浏览器 javascript 同源策略
2021-08-07 23:44:44

我无法完全理解同源域的含义。我知道这意味着当从另一个域(例如 JS 文件)获取资源时,它将从为其提供服务的域的上下文中运行(如 Google Analytics 代码),这意味着它无法修改数据或读取数据在“包含资源”的域上。

因此,如果域在其源中a.com嵌入了一个 js 文件,那么该 js 将从中运行并且它无法访问 DOM\cookies\ 上的任何其他元素——对吗?google.com google.coma.com

这是我无法理解的同源策略的定义:

同源策略是在浏览器中实现的一种关键机制,旨在防止来自不同来源的内容相互干扰。基本上,允许从一个网站接收的内容读取和修改从同一站点接收的其他内容,但不允许访问从其他站点接收的内容。

那个的真实意义是什么?你能给我一个现实生活中的例子吗?

另一个问题是:Origin 标头的目的是什么,跨域请求如何仍然存在?为什么不影响安全或同源策略?

4个回答

为什么同源政策很重要?

假设您登录 Facebook 并在另一个浏览器选项卡中访问恶意网站。如果没有同源策略,该网站上的 JavaScript 可以对您的 Facebook 帐户执行您被允许执行的任何操作。例如,在您输入密码后阅读私人消息、发布状态更新、分析 HTML DOM 树,然后再提交表单。

但当然 Facebook 希望使用 JavaScript 来增强用户体验。因此,浏览器能够检测到此 JavaScript 是否受信任以访问 Facebook 资源非常重要。这就是同源策略发挥作用的地方:如果 JavaScript 包含在 facebook.com 上的 HTML 页面中,它可能会访问 facebook.com 资源。

现在用您的网上银行网站替换 Facebook,很明显这是一个问题。

起源是什么?

我无法完全理解同源域的含义。我知道这意味着当从另一个域(例如 JS 文件)获取资源时,它将从为其提供服务的域的上下文中运行(如谷歌分析代码),这意味着它无法修改数据或读取数据在“包含资源”的域上。

这是不正确的:JavaScript 文件的来源是由包含它的 HTML 页面的域定义的。因此,如果您包含带有 <script>-tag 的 Google Analytics 代码,它可以对您的网站执行任何操作,但在 Google 网站上没有相同的来源权限。

跨域通信如何工作?

并非对所有请求都强制执行相同的源策略。其中 <script>- 和 <img>-标签可以从任何域中获取资源。也可以发布表格和链接到其他域。框架和 iframe 方式显示来自其他域的信息,但与该内容的交互受到限制。

有一些方法可以以安全的方式允许 XMLHttpRequest (ajax) 调用其他域,但普通浏览器并不能很好地支持它们。启用与另一个域通信的常用方法是JSONP

它基于 <script>-tag。应该发送到另一个域的信息在 URL 中编码为参数。返回的 JavaScript 包含一个以请求信息作为参数的函数调用:

<script type="text/javascript" src="http://example.com/
     ?some-variable=some-data&jsonp=parseResponse">
</script>

从 example.com 动态生成的 JavaScript 可能如下所示:

parseResponse({"variable": "value", "variable2": "value2"})

什么是跨站脚本?

Cross Site Scripting是一个允许攻击者将 JavaScript 代码注入网站的漏洞,从浏览器的角度来看,它源自被攻击的网站。

如果用户输入没有得到足够的净化,就会发生这种情况。例如,搜索函数可能会显示字符串“您对 [userinput] 的搜索结果”。如果 [userinput] 没有被转义,攻击者可能会搜索:

<script>alert(document.cookie)</script>

浏览器无法检测到这段代码不是由网站所有者提供的,所以它会执行它。如今,跨站点脚本是一个主要问题,因此已采取措施防止此漏洞。最值得注意的是内容安全策略方法。

那个的真实意义是什么?你能给我一个现实生活中的例子吗?

攻击示例 1:使用 HTML 表单的跨站请求伪造 (CSRF)

evil.com攻击者的页面上放了:

<form method="post" action="http://bank.com/trasfer">
    <input type="hidden" name="to" value="ciro">
    <input type="hidden" name="ammount" value="100000000">
    <input type="submit" value="CLICK TO CLAIM YOUR PRIZE!!!">
</form>

没有进一步的安全措施:

  • 请求确实被发送。SOP 不禁止发送此请求。
  • 它包括您从中登录的身份验证 cookie bank.com。如“是否禁止所有跨域请求?”中所述。例如,跨域发送 cookie 允许您单击<a链接bank.com并转到已登录的网站,这是用户通常想要的。

它是同步器令牌模式,单独,即使没有 SOP,也阻止了它的工作。

同步器令牌模式

对于 上的每一个表单bank.com,开发者都会生成一个一次性随机序列作为隐藏参数,并且只有在服务器获取到参数时才接受请求。

例如,Rails 的 HTML 助手会自动向 HTML 添加一个authenticity_token参数,因此合法的表单如下所示:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token"
            value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100000000"></p>
  <p><button type="submit">Send 100000000$ to Ciro.</button></p>
</form>

如所述:https : //stackoverflow.com/questions/941594/understanding-the-rails-authenticity-token/26895980#26895980

因此,如果evil.com发出一个单一的请求,他们永远不会猜到那个令牌,服务器会拒绝交易!

另请参阅:OWASP 的同步器令牌模式

攻击示例 2:使用 JavaScript AJAX 的跨站请求伪造 (CSRF)

但是,是什么阻止了evil.com使用 JavaScript 发出 2 个请求,就像合法浏览器会做的那样:

  1. 令牌的 XHR GET
  2. 包含好令牌的 XHR POST

所以evil.com会尝试这样的事情(jQuery 因为懒惰):

$.ajax({
  url: 'http://bank.com/transfer',
  type: "GET",
  xhrFields: {withCredentials: true},
});
// Parse HTML reply and extract token.
$.ajax({
  url: 'http://bank.com/transfer',
  type: "POST",
  data: {
    to: 'ciro',
    ammount: '100000000',
    authenticity_token: extracted_token
  },
  xhrFields: {withCredentials: true},
});

攻击者在这里使用withCredentials: true,因为没有它 XHR 不会发送交叉请求 cookie,另请参阅:为什么 cookie 与 HTML 页面的跨域请求一起发送,但不与 JS 的 XHR 一起发送?

就是 SOP 发挥作用的地方。尽管GET 和 POST 实际上确实像 HTML 表单一样发送经过身份验证的请求,但发送者的浏览器阻止 JavaScript 代码读取 HTML 回复,因为请求被发送到单独的域!

Chromium 开发者控制台显示一个错误类型:

从源“http://evil.com”访问“http://bank.com”中的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。

已在以下位置询问:https ://stackoverflow.com/questions/20035101/why-does-my-javascript-code-get-a-no-access-control-allow-origin-header-is-pr

为什么不直接发送交叉请求 cookie 呢?

如果实现有这样的规则:“允许任何请求,但只在当前域 XHR 上发送 cookie”怎么办?那不是更简单吗?

但这仍然允许另一种类型的攻击:当身份验证不是基于 cookie,而是基于请求的源 (IP) 时!

例如,您在公司的 Intranet 中,您可以从那里访问内部服务器,该服务器从外部不可见并提供秘密数据。

是否禁止所有跨域请求?

即使忘记 CORS,,我们每天都在做!

唯一不能允许的就是在 JavaScript 中读回此类请求的结果,因为这会击败同步器令牌模式。

来自MDN

  • 通常允许跨域写入:链接、重定向和表单提交。

    [我的评论]:例如,当您单击链接时,您通常希望登录到该网站,这需要发出经过身份验证的 GET 请求以返回新页面。

  • 通常允许跨域嵌入:图像、外部 CSS 和 Javascript、iframe。

  • 通常不允许跨域读取:XHR(上面的示例),iframe读取。

    但是,读取访问权限通常会因嵌入而泄露。例如,您可以读取嵌入图像的宽度和高度、嵌入脚本的操作或嵌入资源的可用性(因此可能会在用户登录或未登录给定域的情况下)

其他预防方法

其他预防方法:智威汤逊

JSON Web Token是 2020 年左右 cookie + 同步器令牌模式的相当流行的替代方案。

这个方法的作用是:

  • 将签名令牌存储在 window.localStorage
  • 每当您想向服务器发出经过身份验证的请求时,请发送一个 header Authentication: <token>请注意,这只能通过 JavaScript 完成。

此方法之所以有效,是因为与 cookie 不同,localStorage它仅在您从网站本身(通过 JavaScript)发出请求时可用,从而分配同步器令牌。

然后,当用户第一次访问该网站时,他们最初会被注销,并显示一个虚拟加载页面。

然后浏览器运行刚刚从服务器接收到的 JavaScript,读取localStorage(现在我们已经在正确的域中)并向 API 路径发送经过身份验证的 GET 请求,以仅获取没有 HTML 的数据,通常为 JSON。

最后,JavaScript 在浏览器上呈现该数据。

由于单页应用程序的流行,这种方法变得特别流行,其中最简单的实现方法是这个两步获取虚拟页面,然后用 API 数据填充它。

所以这基本上进行了权衡:

  • 好处:
    • 更容易实现,因为每个表单上都没有同步器
    • 通常的 SPA 优势:在初始请求后您只获得数据,而不是 HTML 标记
  • 缺点:
    • 通常的SPA缺点:
      • 在第一次加载期间,用户可能会看到令人讨厌的加载虚拟页面元素
      • 没有 JavaScript 网站是不可见的

也可以看看

别担心。我发现把头绕起来也很棘手。

事实证明,理论上,Google Analytics 可以对您的用户做任何他们想做的事情。<script>标签创建同源策略限制的例外)

这是XSS攻击成为坏事™的最大原因之一,也是 Mozilla 设计内容安全策略的一个原因,策略现在正朝着标准化的方向发展。(WebKit 对 HTML5 iframe 沙盒属性的实现也有帮助)

因为他们无法摆脱向后兼容性,所以同源策略更多地是关于防止诸如使用“记住我”cookie或欺骗登录对话框访问您的帐户之类的技巧<iframe>XMLHttpRequestX-Frame-Options标头允许您进一步锁定帧以防止诸如Clickjacking之类的事情。)

Origin头由名为“跨域资源共享”的机制使用,该机制允许站点授予同源策略的有限例外,以实现安全的跨站点交互。(在除 Opera 和 Internet Explorer 之外的所有当前浏览器中完全支持,在 IE8+ 中部分支持,使用省略 cookie 的专有 XDomainRequest 对象)

基本上,当您尝试创建XMLHttpRequest一个不同的域时,浏览器将执行以下两项操作之一

  1. 如果它是一个满足某些限制的GETPOST请求(标准的制定者已经确定不会增加CSRF攻击的额外风险),那么浏览器只会通过该请求。

  2. 否则,它会执行所谓的“预检请求”,它首先发送OPTIONS请求,并且仅在检查通过请求时才执行您请求的操作OPTIONS

在任何一种情况下,浏览器都会附加一个Origin标题,告诉目标站点谁在调用。(它有点像Referer标题,但需要并且更严格地指定以确保适当的安全性)

然后,接收端的服务器(严重依赖同源策略进行保护的服务器)可以通过包含一个Access-Control-Allow-Origin包含请求标头*值或值的标头来授权请求Origin

如果没有,浏览器会简单地丢弃响应并向 Javascript 回调返回错误。MDN 详细介绍了(1) (2)在这两种情况下的幕后情况以及目标系统可以设置哪些其他标头以进一步以受控方式放松安全性。(例如,允许访问您正在设置的自定义 HTTP 标头)

GET除非目标 Web 应用程序受到适当保护,否则请求和允许的POST请求子集已经可以通过其他机制用于 CSRF 攻击,因此决定将操作服务(如 Google Font)所涉及的 HTTP 请求数量增加一倍没有任何好处图书馆。

其实在这种情况下,谷歌解析脚本的来源是a.com

引用JavaScript:权威指南

重要的是要了解脚本本身的来源与同源策略无关:重要的是嵌入脚本的文档的来源。