跨源资源共享是一种机制,允许网页向另一个域发送xmlhttprequest(来自维基百科)。
在过去的几天里,我一直在摆弄CORS,我认为我对每件事情的工作原理都有很好的理解。
所以我的问题不是关于CORS /预飞是如何工作的,而是关于将预飞作为一种新的请求类型背后的原因。我看不出为什么服务器A需要发送一个preflight (PR)到服务器B,只是为了找出真实的请求(RR)是否会被接受——B当然有可能在没有任何预先PR的情况下接受/拒绝RR。
在搜索了相当多之后,我在www.w3.org(7.1.5)上找到了这条信息:
为了保护资源不受在本规范存在之前不能来自某些用户代理的跨源请求的影响,a
发出飞行前请求,以确保资源知道这一点
规范。
我发现这是最难理解的句子。我的解释(最好称之为“最佳猜测”)是关于保护服务器B不受服务器C的请求,因为服务器C不知道该规范。
谁能解释一个场景/展示一个PR + RR比RR单独解决更好的问题?
考虑一下CORS之前的跨域请求世界。您可以执行标准表单POST,或者使用脚本或图像标记来发出GET请求。除了GET/POST之外,您不能创建任何其他请求类型,并且不能对这些请求发出任何自定义头。
随着CORS的出现,规范作者面临着在不破坏现有web语义的情况下引入新的跨域机制的挑战。他们选择通过为服务器提供一种选择任何新请求类型的方法来做到这一点。这个选择是飞行前的请求。
因此,没有任何自定义报头的GET/POST请求不需要preflight,因为这些请求在CORS之前就已经可以实现了。但是任何带有自定义报头的请求,或PUT/DELETE请求,都需要预先处理,因为这些是CORS规范的新内容。如果服务器对CORS一无所知,它将在没有任何CORS特定报头的情况下进行回复,并且不会发出实际的请求。
如果没有preflight请求,服务器可能会开始看到来自浏览器的意外请求。如果服务器没有为这些类型的请求做好准备,这可能会导致安全问题。CORS preflight允许以安全的方式将跨域请求引入web。
我觉得其他的答案并没有把重点放在战前提高安全性的原因上。
场景:
1) With pre-flight. An attacker forges a request from site dummy-forums.com while the user is authenticated to safe-bank.com
If the Server does not check for the origin, and somehow has a flaw, the browser will issue a pre-flight request, OPTION method. The server knows none of that CORS that the browser is expecting as a response so the browser will not proceed (no harm whatsoever)
2) Without pre-flight. An attacker forges the request under the same scenario as above, the browser will issue the POST or PUT request right away, the server accepts it and might process it, this will potentially cause some harm.
如果攻击者直接从某个随机主机发送请求,那么很有可能是没有经过身份验证的请求。这是伪造的请求,但不是xsrf请求。服务器会检查凭证并失败。
CORS并不试图阻止拥有发出请求的凭据的攻击者,尽管白名单可以帮助减少这种攻击向量。
预飞行机制增加了客户端和服务器之间的安全性和一致性。
我不知道这是否值得为每个请求额外握手,因为缓存在那里是可以使用的,但这就是它的工作原理。
下面是另一种看待它的方式,使用代码:
<!-- hypothetical exploit on evil.com -->
<!-- Targeting banking-website.example.com, which authenticates with a cookie -->
<script>
jQuery.ajax({
method: "POST",
url: "https://banking-website.example.com",
data: JSON.stringify({
sendMoneyTo: "Dr Evil",
amount: 1000000
}),
contentType: "application/json",
dataType: "json"
});
</script>
在cors之前,上述利用尝试将会失败,因为它违反了同源策略。以这种方式设计的API不需要XSRF保护,因为它受到浏览器本地安全模型的保护。cors之前的浏览器不可能生成跨源JSON POST。
现在CORS出现了——如果不需要通过飞行前选择加入CORS,突然之间这个网站就会有一个巨大的漏洞,这不是他们自己的过错。
为了解释为什么一些请求被允许跳过预飞行,这是在规范中回答的:
简单的跨源请求被定义为与这些请求一致
哪些可能是由当前部署的用户代理生成的
遵守这个规范。
为了解决这个问题,GET没有预先运行,因为它是7.1.5中定义的“简单方法”。(标题也必须“简单”,以避免预飞行)。
这样做的理由是,“简单的”跨源GET请求已经可以通过例如<script src="">来执行(这是JSONP的工作方式)。由于任何具有src属性的元素都可以触发跨源GET,没有预先飞行,因此在“简单”xhr上要求预先战斗将没有安全好处。