浏览器是不是允许“发送”跨域请求?
Posted
技术标签:
【中文标题】浏览器是不是允许“发送”跨域请求?【英文标题】:Do browsers allow cross-domain requests to be "sent"?浏览器是否允许“发送”跨域请求? 【发布时间】:2017-03-07 09:56:50 【问题描述】:我是网站安全的新手,目前正试图深入了解 Same-Origin-Policy。 虽然在 *** 和其他地方有关于 SOP 概念的非常好的帖子,但我找不到关于 chrome 和其他浏览器是否允许跨域 XHR 发布请求'发送更新信息/strong>' 从一开始就是这样。
从this 5 岁的帖子来看,chrome 似乎允许请求传递到请求的服务器,但不允许读取请求者的响应。
我在我的网站上进行了测试,试图从不同的域更改我服务器上的用户信息。详情如下:
-
我的域:“www.mysite.com”
攻击者域:“www.attacker.mysite.com”
根据 Same-Origin-Policy,这两个被认为是不同的起源。
用户(登录到 www.mysite.com 时)打开 www.attacker.mysite.com 并按下一个按钮,向“www.mysite.com”服务器发出 POST 请求...提交的隐藏表单(在这种情况下没有令牌)具有更改“www.mysite.com”服务器上的用户信息所需的所有信息 --> 结果:CSRF 成功攻击:用户信息确实发生了变化。
现在做同样的事情,但使用 javascript 通过 JQuery .post
提交表单而不是提交表单--> 结果:除了 chrome 给出正常响应:
请求中没有“Access-Control-Allow-Origin”标头 资源
,我发现服务器端没有做任何更改......似乎请求甚至没有从浏览器通过。用户信息根本没有改变!虽然这听起来不错,但我的预期正好相反。
根据我的理解和上面链接的帖子,对于跨域请求,只有服务器响应应该被浏览器阻止而不是从一开始就向服务器发送帖子请求。
另外,我没有任何 CORS 配置集;没有发送Access-Control-Allow-Origin headers
。但即使我有那个设置,它也应该只适用于“读取”服务器响应而不是实际发送请求......对吗?
我想到了预检,发送请求以检查服务器是否允许它,从而在发送实际数据以更改用户信息之前阻止请求。但是,根据 Access_Control_CORS ,这些预检仅在不适用于我的简单 AJAX 发布请求的特定情况下发送(其中包括一个简单的表单,默认情况下为 application/x-www-form-urlencoded
并且不发送自定义标头)。
那么,是不是 chrome 已经改变了它的安全规范,从一开始就阻止了对跨域的 post 请求? 还是我对同源策略的理解在这里遗漏了什么?
无论哪种方式,了解是否有在不同网络浏览器中实施的更新安全措施的来源会很有帮助。
【问题讨论】:
Buy 攻击者只能使用表单帖子,为什么还要使用 XHR 来妨碍自己? 是的...我只是在探索 SOP 的限制以及它的行为方式。 我刚刚观察到这一点,正要在 SO 上提出这个问题,但偶然发现了这篇文章。 【参考方案1】:好的……我明白了……这既不是 chrome 的新政策,也不是 SOP 中的遗漏…… "www.mysite.com" 的会话 cookie 设置为 "HttpOnly",这意味着,如 here 所述,它们不会与 AJAX 请求一起发送,因此服务器不会更改用户的详细信息第 (4) 点。
在我的 post 请求中添加 xhrFields: withCredentials:true
后,我就能够按预期在跨域 XHR POST 调用中更改用户信息。
虽然这证明了浏览器实际上向服务器发送跨域 post 请求并且只阻止服务器响应这一已知事实,但它可能仍然有助于那些试图加深对 SOP 的理解和/或玩CORS。
【讨论】:
【参考方案2】:随着时间的推移,XMLHttpRequest
对象的行为已被重新审视。
第一个 AJAX 请求不受约束。
引入 SOP 时,XMLHttpRequest
已更新以限制每个跨域请求
如果 url 的来源与 XMLHttpRequest 的来源不同,则用户代理应引发 SECURITY_ERR 异常并终止这些步骤。
来自XMLHttpRequest Level 1,open
方法
这个想法是,无法读取响应的 AJAX 请求是无用的并且可能是恶意的,因此它们被禁止。 所以一般来说,跨域 AJAX 调用永远不会到达服务器。 此 API 现在称为 XMLHttpRequest Level 1。
事实证明,SOP 通常过于严格,在开发 CORS 之前,微软开始提供(并试图标准化)一个新的XMLHttpRequest2
API,它只允许一些特定的请求,被任何 cookie 和大多数标头剥离.
标准化失败并在 CORS 出现后被合并回 XMLHttpRequest
API。 Microsoft API 的行为大部分被保留,但更复杂(阅读:潜在危险)的请求被允许在服务器的特定允许下(通过使用预飞行)。
带有non simple headers or Content-Type 的POST 请求被认为是复杂的,因此它需要预检。
预检是通过 OPTIONS 方法完成的,并且不包含任何表单信息,因此不会在服务器上进行任何更新。 当 pre-flight 失败时,用户代理(浏览器)终止 AJAX 请求,保留 XMLHttpRequest Level 1 行为。
简而言之:对于XMLHttpRequest
,SOP 更强,尽管 SOP 原则规定了目标,但拒绝任何跨域操作。这是可能的,因为当时这并没有破坏任何东西。
CORS 放宽了默认情况下允许“无害”请求并允许与其他请求协商的政策。
【讨论】:
感谢您的精彩概述...您是否考虑共享一个从中获取此类信息的资源?了解事物发展过程背后的历史总是很有趣。 但是,如果来自跨源请求者的 POST 请求确实被服务器处理(未启用 CORS),这不算有害吗?服务器的状态已被不应执行的请求更改。 @Sнаđошƒаӽ 是的,这将是有害的,但 SOP 的重点是防止任何网站读取任何其他网站(因为这会从经过身份验证的会话中访问数据)。您所描述的是一个CSFR,这可以通过例如表单令牌来避免。由网站来实施安全策略,但需要 SOP,因为网站无法判断 read 请求是否合法。请注意,无法读取 POST 请求响应。见this @Sнаđошƒаӽ 至于“为什么首先允许 POST”,嗯......我不确定。我相信这是因为它是 HTTP 的一个设计特性,the W3C kind of said something like that。可能,他们严格关注主要问题:阅读第三方网站,并不想禁止写作。以上是关于浏览器是不是允许“发送”跨域请求?的主要内容,如果未能解决你的问题,请参考以下文章