简体   繁体   English

同源策略的机制是什么以及为什么不预先发送简单的 post 请求

[英]What is the mechanism of the same-origin-policy and why aren't simple post requests pre-flighted

  1. What are the actual mechanisms of the same-origin-policy and how is it different to cors and同源策略的实际机制是什么,它与 cors 和
  2. Why simple post requests are not pre-flighted since a post request can change state on a server.为什么简单的 post 请求没有预先发送,因为 post 请求可以更改服务器上的 state。

To my understanding, the same origin policy has two main implementations, with complex requests a pre-flight request is initially sent to determine if the main request should be sent, and with simple requests, the browser just checking the access-control-allow-origin header on the response of a request.据我了解,同源策略有两个主要实现,对于复杂请求,最初发送飞行前请求以确定是否应发送主请求,对于简单请求,浏览器只需检查访问控制允许-起源 header 对请求的响应。

Thus, with a simple post request, the access-control-allow-origin header of a response simply prevents javascript from reading the response, but the request still goes through to the server.因此,通过一个简单的 post 请求,响应的 access-control-allow-origin header 只会阻止 javascript 读取响应,但请求仍会通过服务器。 Thus, a csrf attack could still go through with a simple post request.因此,csrf 攻击仍然可以通过简单的 post 请求进行 go。

As a side note, the above understanding is based on https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#cross-origin_network_access , 'writes are typically allowed' meaning a simple request can go through to a server, 'cross-origin reads are typically disallowed', without the request's origin header matching the access-control-allow origin, reads are disallowed by the browser.作为旁注,上述理解基于https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#cross-origin_network_access ,“通常允许写入”意味着一个简单的请求可以go 到服务器,“通常不允许跨域读取”,如果请求的来源 header 与访问控制允许来源匹配,则浏览器不允许读取。 'Some HTTP requests require preflight', complex requests require pre-flight. '一些 HTTP 请求需要预检',复杂的请求需要预检。 Me filling in the gaps of SOP's implementation is due to the my lack of understanding of the above linked docs in SOP's mechanism, and sources such as the 'Details' chapter of this link https://www.w3.org/Security/wiki/Same_Origin_Policy#:~:text=The%20same%2Dorigin%20policy%20restricts,origin%20PUT%20and%20DELETE%20requests .我填补 SOP 实施的空白是由于我对 SOP 机制中的上述链接文档以及此链接的“详细信息”章节等来源缺乏了解https://www.w3.org/Security/wiki /Same_Origin_Policy#:~:text=%20same%2Dorigin%20policy%20restricts,origin%20PUT%20and%20DELETE%20requests explaining a very similar process between the MDN Docs' explanation of CORS and SOP.解释了 MDN 文档对 CORS 和 SOP 的解释之间非常相似的过程。 Thus, my understanding of SOP vs CORS, is that prior to the invention of CORS, the pre-flight requests and access-control-allow headers were already implemented by SOP, but CORS is simply the changing of the access-control-allow headers within the responses.因此,我对 SOP 与 CORS 的理解是,在 CORS 发明之前,SOP 已经实现了飞行前请求和访问控制允许标头,但是 Z5A8FEFF0B4BDE3EEC9244B76023B791 的标头只是更改了访问控制-允许标头在回复中。

Continuing with the my main post, this SO answer https://stackoverflow.com/a/39736697/19752150 attempts to explain why a post request is deemed simple and thus not subject to pre-flight.继续我的主要帖子,这个 SO 答案https://stackoverflow.com/a/39736697/19752150试图解释为什么一个帖子请求被认为是简单的,因此不受飞行前的影响。

But prior to CORS, browsers wouldn't allow you to do a cross-origin application/json POST at all, and so servers could assume they wouldn't receive them.但在 CORS 之前,浏览器根本不允许您执行跨域应用程序/json POST,因此服务器可能会假设他们不会收到它们。

To my understanding, the history of csrf attacks goes something like, csrf attacks became a thing, browsers implemented the same-origin policy to stop csrf attacks, we wanted to be able to send cross-origin requests, CORS was made.据我了解,csrf 攻击的历史是这样的,csrf 攻击成为了一个东西,浏览器实施了同源策略来阻止 csrf 攻击,我们希望能够发送跨域请求,CORS 被提出。

So this answer is confusing on two fronts.所以这个答案在两个方面令人困惑。 1. 'browsers wouldn't allow you to do a cross-origin application/json POST at all'. 1. '浏览器根本不允许你进行跨域应用程序/json POST'。 the same-origin-policy makes it so that these requests are allowed to still get sent to the server, but the js just can't read the response.同源策略使得这些请求仍然被允许发送到服务器,但是 js 就是无法读取响应。 2. The SO question asks why CORS doesn't make simple post requests send a pre-flight request, and thus this answer suggests that somewhere prior to CORS, browsers had some method of preventing cross-origin requests from being sent in its entirety, suggesting that SOP is the one responsible for this. 2. SO问题询问为什么CORS不让简单的post请求发送飞行前请求,因此这个答案表明在CORS之前的某个地方,浏览器有一些方法可以防止跨域请求被完整发送,建议 SOP 对此负责。 But with what mechanism does SOP then do this?但是 SOP 是通过什么机制做到这一点的呢? And building on my previously stated understanding of SOP, doesn't SOP only prevent reads by the js but still let the request go through successfully to the server for simply requests?并且基于我之前对 SOP 的理解,SOP 是否不仅阻止了 js 的读取,但仍然让请求 go 成功通过服务器进行简单请求?

Thus, my main questions are still因此,我的主要问题仍然是

  1. what are the actual mechanisms of the same-origin-policy and what is its difference with cors and同源策略的实际机制是什么,它与 cors 和有什么区别
  2. why simple post requests are not pre-flighted since a post request can change state on a server.为什么简单的 post 请求没有预先发送,因为 post 请求可以更改服务器上的 state。 However, if at any point in the post I have a faulty misunderstanding, please correct me then as well.但是,如果在帖子中的任何一点我有错误的误解,也请纠正我。

Allow me to analyse your question step by step...请允许我逐步分析您的问题...

What are the actual mechanisms of the same-origin-policy and how is it different to cors同源策略的实际机制是什么,与cors有何不同

The Same-Origin Policy (SOP) is a relatively loose set of object-access and network-access restrictions that forms the basis of modern Web security.同源策略 (SOP)是一组相对宽松的对象访问和网络访问限制,forms 是现代 Web 安全性的基础。 It revolves around the concept of Web origin .它围绕Web origin的概念展开。

Cross-Origin Resource Sharing (CORS) is a mechanism that a server can opt in so as to instruct browsers to selectively lift some of the SOP's network-access restrictions on both sending (requests) and reading (responses) for the server's clients;跨域资源共享 (CORS)是一种服务器可以选择加入的机制,以指示浏览器有选择地解除 SOP 对服务器客户端发送(请求)和读取(响应)的一些网络访问限制; client here is to be understood as "Web content loaded in your browser that communicates with the server".此处的客户端应理解为“加载到您的浏览器中并与服务器通信的 Web 内容”。

Don't conflate the SOP and CORS.不要将 SOP 和 CORS 混为一谈。 No metaphor is perfect but, if the SOP is akin to a seatbelt, CORS is the button to unbuckle that seatbelt;没有什么比喻是完美的,但是,如果 SOP 类似于安全带,那么 CORS 就是解开安全带的按钮; and unbuckling a seatbelt never makes you more secure.解开安全带永远不会让你安全。

Why simple post requests are not pre-flighted since a post request can change state on a server.为什么简单的 post 请求没有预先发送,因为 post 请求可以更改服务器上的 state。

CORS preflight is a mechanism that browsers use to check whether the server understand the CORS protocol. CORS 预检是浏览器用来检查服务器是否理解 CORS 协议的机制。 Introduce that mechanism was necessary in order to protect old servers that predate support for JavaScript-based cross-origin requests and CORS against cross-origin abuse.引入该机制是必要的,以保护早于支持基于 JavaScript 的跨域请求和 CORS 的旧服务器免受跨域滥用。 However, CORS preflight is not a general-purpose defence mechanism against cross-origin request forgery (traditionally called cross-site request forgery , or CSRF for short, but the technical meaning of site has since shifted, which now makes CSRF a problematic term).但是,CORS preflight 并不是针对跨域请求伪造的通用防御机制(传统上称为跨站点请求伪造,简称CSRF ,但是站点的技术含义已经发生了转变,这使得 CSRF 现在成为一个有问题的术语) . As you perceived correctly, simple POST requests can be forged and, if accepted by the server, can change the latter's state.正如您正确理解的那样,可以伪造简单的POST请求,如果服务器接受,可以更改后者的 state。

To my understanding, the same origin policy has two main implementations, with complex requests a pre-flight request is initially sent to determine if the main request should be sent, and with simple requests, the browser just checking the access-control-allow-origin header on the response of a request.据我了解,同源策略有两个主要实现,对于复杂请求,最初发送飞行前请求以确定是否应发送主请求,对于简单请求,浏览器只需检查访问控制允许-起源 header 对请求的响应。

That's more or less correct, except for your conflation of the SOP with CORS.这或多或少是正确的,除了您将 SOP 与 CORS 混为一谈。

Thus, with a simple post request, the access-control-allow-origin header of a response simply prevents javascript from reading the response, but the request still goes through to the server.因此,通过一个简单的 post 请求,响应的 access-control-allow-origin header 只会阻止 javascript 读取响应,但请求仍会通过服务器。 Thus, a csrf attack could still go through with a simple post request.因此,csrf 攻击仍然可以通过简单的 post 请求进行 go。

Correct.正确的。 Forging simple requests from another origin is still possible.仍然可以伪造来自另一个来源的简单请求。 More on that further down my answer.更多关于我的回答。

[...] prior to the invention of CORS, the pre-flight requests and access-control-allow headers were already implemented by SOP, but CORS is simply the changing of the access-control-allow headers within the responses. [...] 在 CORS 发明之前,飞行前请求和访问控制允许标头已由 SOP 实现,但 CORS 只是在响应中更改访问控制允许标头。

The SOP predates the CORS protocol and thus, CORS preflight. SOP 早于 CORS 协议,因此早于 CORS 预检。 But you're right that all those Access-Control-* headers are part of the CORS protocol and didn't have any semantics beforehand.但是你是对的,所有这些Access-Control-*标头都是 CORS 协议的一部分,并且事先没有任何语义。

[...] csrf attacks became a thing, browsers implemented the same-origin policy to stop csrf attacks, we wanted to be able to send cross-origin requests, CORS was made. [...] csrf 攻击成为现实,浏览器实施了同源策略来阻止 csrf 攻击,我们希望能够发送跨域请求,CORS 被提出。

The SOP's main objective was to restrict cross-origin reading; SOP 的主要目标是限制跨域阅读; for instance, to avoid http://attacker.com from sending authenticated requests to https://mybank.com and reading your account's balance from the response. for instance, to avoid http://attacker.com from sending authenticated requests to https://mybank.com and reading your account's balance from the response. The SOP could not have forbidden all cross-origin requests; SOP 不可能禁止所有跨域请求; otherwise, the Web would arguably be unusable.否则,Web 可能无法使用。

  1. 'browsers wouldn't allow you to do a cross-origin application/json POST at all'. “浏览器根本不允许您进行跨域应用程序/json POST”。 the same-origin-policy makes it so that these requests are allowed to still get sent to the server, but the js just can't read the response.同源策略使得这些请求仍然被允许发送到服务器,但是 js 就是无法读取响应。

The SOP places restrictions on the content-type of cross-origin requests. SOP 对跨域请求的内容类型进行了限制。 The essence of the MIME type must be one of the three values historically allowed by HTML forms: MIME类型的本质必须是HTML forms历史上允许的三个值之一:

  • application/x-www-form-urlencoded
  • text/plain
  • multipart/form-data

Attempts to send a cross-origin request with Content-Type: application/json will cause the browser to trigger CORS preflight.尝试使用Content-Type: application/json发送跨域请求将导致浏览器触发 CORS 预检。 The actual request won't even get sent unless the server agrees by replying "yes" to the preflight request automatically sent by the browser.除非服务器通过对浏览器自动发送的预检请求回复“是”来表示同意,否则实际请求甚至不会被发送。

However, as a backend developer, you must be careful, because the advent of the Fetch API allowed things that were previously impossible.但是,作为后端开发人员,您必须小心,因为 Fetch API 的出现允许了以前不可能的事情。 In particular, anyone can use fetch to craft a simple request (with a Content-Type of value text/plain , say) whose body contains well formatted JSON:特别是,任何人都可以使用fetch来制作一个简单的请求(比如 Content-Type 值为text/plain ),其正文包含格式良好的 JSON:

fetch("https://example.com", {method: "POST", body: JSON.stringify({"foo": "foo"})})

To fix ideas, if you open your browser's Console tab and paste the statement above, you should see something like the following request on the wire:要修正想法,如果您打开浏览器的控制台选项卡并粘贴上面的语句,您应该会在网络上看到类似于以下请求的内容:

POST / HTTP/1.1
Host: example.com
Content-Length: 13
Sec-Ch-Ua: "Chromium";v="103", ".Not/A)Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.134 Safari/537.36
Sec-Ch-Ua-Platform: "macOS"
Content-Type: text/plain;charset=UTF-8
Accept: */*
Origin: https://stackoverflow.com
Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://stackoverflow.com/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: close

{"foo":"foo"}

Because the request remains simple (not preflighted ), the browser, in accordance with the rules of the SOP, has no objection to sending a request with such a body to the server.由于请求保持简单(未预检),浏览器按照 SOP 的规则,不反对向服务器发送带有这种正文的请求。 Actually, sending well-formatted JSON is also possible with a HTML form, but I leave that to you an exercise.实际上,使用 HTML 表格也可以发送格式良好的 JSON ,但我把它留给你练习。 For more about this overly permissive sending restrictions in general, see section 4 of Chen et al.'s 2018 USENIX paper .有关这种过度宽松的发送限制的更多信息,请参阅Chen 等人 2018 年 USENIX 论文的第 4 节。

Because cross-origin attackers can (and do ) exploit this, even if you expect requests containing JSON, you still need to implement defences against cross-origin abuse.因为跨域攻击者可以(并且确实)利用这一点,即使您期望包含 JSON 的请求,您仍然需要实施针对跨域滥用的防御。 See OWASP's cheat sheet on the topic .请参阅OWASP 关于该主题的备忘单

For a great retrospective on the SOP (with a focus on object-access restrictions rather than on network-access ones, though), see LiveOverflow's recent video .有关 SOP 的精彩回顾(不过,重点是对象访问限制而不是网络访问限制),请参阅LiveOverflow 最近的视频

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM