CROS 同源问题的一些疑问

36 天前
 chinafengzhao

最近在学习 CORS 同源策略问题,看到几个观点:

1 、跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是响应结果被浏览器拦截了。 不仅仅是静态的资源。WebStorage 、Cookie 、IndexDB ,在浏览器层面上都是以域这一概念来划分管理的。 而且这个划分管理行为,就是在浏览器本地生效。和服务器、其他客户端没有直接关系。

2 、当响应的是附带身份凭证的请求时,服务端必须明确 Access-Control-Allow-Origin 的值,而不能使用通配符。

针对 1 ,比如说我做为可能有恶意脚本的黑客,不管你请求头带不带 origin ,我返回的 js 响应报文中,我始终带上 "Access-Control-Allow-Origin: *"这个响应头啊。 这样我的恶意 js 不就可以被浏览器解释并执行了?

针对 2 ,这个服务端必须是为什么要必须明确呢?如果不明确会怎么样呢? CORS 做为一个浏览器对资源请求的约束,它咋知道我的请求带不带身份呢?

请教各位大佬赐教一下

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Guides/CORS

https://zhuanlan.zhihu.com/p/38972475

2423 次点击
所在节点    信息安全
26 条回复
lululau
36 天前
我理解所谓「同源策略」是用来防止 CSRF 的而不是 XSS 的吧
FlyaiF
36 天前
应该是为了防止浏览器里边进行一些假冒的网站,引导用户做一些用户意料外的操作吧
hurrytospring
36 天前
1. 对,但是需要理解安全机制防的是什么,cors 机制中,防范的是跨站脚本攻击,比如在 A 网站中,发起一个对你服务( B )的请求,这个时候就可以携带上 B 的 cookie ,然后在请求中读 B 身份的内容。
至于你说的场景
1.1. 是黑客劫持了响应,然后注入恶意脚本,其实这个时候没有那么麻烦,黑客可以直接劫持 A 的请求。
1.2. 这个场景一般来说是依赖 https 或者更底层的协议来保护,跟 cors 没有关系
2. 身份是一个统一的认证头,key 为 authorization ,如果你就是不用这个 key ,自己设计一个,你就自己越过了这个安全机制,你的服务你自己负责。
2.1 allow:*本质上是一种宽松校验机制,就是如果你认为你这个接口信息不重要,可以让别的站随便拿,你可以定义为*。但是当有这个 header 时,浏览器认为,这不是一个宽松的接口,是含有认证信息的敏感接口,应该采用更严格的校验机制,所以不让你用宽松的配置。
2.2 当然,你可以觉得浏览器说得不对,你换一个认证的 header key ,这个时候浏览器也不对这个事情负责,你可以继续 allow:* ,属于你自己越过安全机制,自己负责
Y25tIGxpdmlk
36 天前
这好比就是正规浏览器遵守的一个保护用户的规则而已吧。

比如有支付宝和微信 2 个网站,如果你用浏览器访问支付宝网站,支付宝如果很坏,里面嵌入了微信的页面。由于微信页面的跨域限制,支付宝页面是不能获取到他嵌入页面的相关数据的,比如 cookie 之类的。虽然对浏览器来说,2 个网站的数据他都有,但是浏览器会遵守一个约定,微信的页面说不能把内容让支付宝看,那他就会隔离 2 个网站。

相应的,如果微信的页面返回里,允许了支付宝,那他的数据就会被共享给支付宝。说白了还是要看浏览器是不是正规,是不是遵守跨域限制。当然你也可以自己魔改一个浏览器或者客户端,直接不遵守跨域限制。
Y25tIGxpdmlk
36 天前
其实你的这类问题,问 ai 是非常好用的,你各种不理解,可以一点点的问他,他会给你讲的非常到位
bronyakaka
36 天前
一个和 cors 无关,自己信任了外部输入并执行,毕竟传过来的本来只是 js 字符串而已;第二个是 csrf
chinafengzhao
36 天前
问过了,并不到位,甚至会乱回答。
cppc
36 天前
1 简单请求是浏览器直接发出,收到服务器响应后拦截

2 非简单请求是先发预检请求,检查服务端响应头,然后根据规则再发实际请求(也就是说可能不会发出真实请求)
AoEiuV020JP
36 天前
cros 是保护用户自己的,入户用户自己是黑客不需要保护,cros 没用的,
比如你作为用户可以安装一个插件“Allow CORS”,就能绕过 cors 的限制,我有时候用一些 web app 会这样,等于允许这个 web app 爬取其他网站的数据,

如果用户不是黑客的话,中间人是靠 https 防范的,
wangtian2020
36 天前
跨域是后端问题,后端问题
禁止是浏览器出于安全,浏览器方面自作主张禁止的,默认假设你的 URL 是对的,如果 URL 不带跨域头那就不让页面收到信息
wangtian2020
36 天前
例如,假如没有跨域限制,那我是不是可以做个跟支 F 宝完全一样的页面,只加一行代码把用户名密码发来
那用户一看页面长的一样,页面行为也一样,不知不觉中就被盗了
seekafter
36 天前
1. 是对的吗? 我理解的是浏览器做出的跨域限制. 因为同样的跨域请求, 浏览器提示 cors, api 工具就会成功
2. 如果携带 cookie, 但设置"Access-Control-Allow-Origin: *", 你的 cookie 会自动被浏览器丢弃.
另外如果你有自定义请求头, 还需要设置响应头为 Access-Control-Allow-Headers: cookie,自定义请求头 1, 头 2... 这个的设置要和你的请求头完全一致
另外前端发请求还需要设置一个 inc 开头的属性. 等我博客启动了发你文章参考下
GeruzoniAnsasu
36 天前
A 域数据被 B 读,你要保护数据,请问是在 A 上设防火墙还是在 B 上?

B 是发起 CORS 请求的站点,现在你理解了不?

如果 A 域数据很敏感,你必然要开个白名单只允许特定 B 来读。除了这个白名单外,你可能希望 A 和 B 上都有一些过滤和拦截,那么浏览器就是 B 上的额外防护层。



你从服务端该怎么响应请求的角度出发会容易理解得多,这也是为什么 CORS 明明只是个很简单的机制但为啥这么多前端一直迷迷糊糊的原因。
pingdog
36 天前
OWASP 记录了大部分攻击手段和防护措施,可以看下他们的文档
irisdev
36 天前
楼主这算是典型初学者的困惑,很多技术在不知道其背景之前总是会产生类似的疑问,其实大多数技术也只是某些场景好用,很多问题是没办法解决的,或者要在可用性、易用性、通用性和绝对安全之间作取舍
fruitmonster
36 天前
V2 不知道为什么这么喜欢讨论跨域请求呢? /t/1056504 /t/1056793
chinafengzhao
36 天前
@seekafter 可以出一篇文章详解一下,等你大作。大家都在说跨域是浏览器行为, 这个我的理解是这样的,浏览器是个公共应用,用户打开浏览器可以访问各种各样的域名各种各样的网站。 网站会在客户端存各种各样的数据(比如用户身份登录态(抱歉这是我自己造的一个词),字体偏好等等(比如通过 session,cookie,webstorage 等),可以理解这是针对域名来对这些数据分开隔离的),所谓大家都在说,不允许带 cookie 啥的。 但是忽略了我的原始问题,不同网站的凭证可能是不同方式实现的,是业务自己私密的实现。这个也不属于标准或协议层面。


**当响应的是附带身份凭证的请求时,服务端必须明确 Access-Control-Allow-Origin 的值,而不能使用通配符“*”。**

协议或者说浏览器要求带这个头部之类的,他怎么判断这个是不是普通请求呢?有些请求里面有 cookie 不代表这是带凭证吧。
@GeruzoniAnsasu
unco020511
36 天前
1 的前提是你主动同意黑客这么干,或者说你就是黑客. 比如你主动在电脑中设置代理,并主动安装根证书到电脑,这样就你的 proxy 就可以随意修改 https 的请求和响应. 更进一步,你直接将你的电脑权限交给黑客.所以 1 已经超出了浏览器同源政策的范畴了
2 的话你可以理解是一个额外安全要求,附带身份凭证会认为是敏感信息,所以有一个额外的安全规定.
不过现在用户凭证很多都不用 cookie 之类的,你想放到哪都可以,比如额外搞个 header 附带 token.
浏览器是一个 httpClicent,当然知道你发送的请求细节,包括 https 的握手加密等细节都是浏览器去实现的,它自然知道,具体到开发中,就是设置 withCredentials 的值,你设置为 true 就认为你带了
chinafengzhao
36 天前
以 MDN 为例,站点 https://foo.example 的网页应用想要访问 https://bar.other 的资源。

如果 https://bar.other 的资源持有者想限制他的资源只能通过 https://foo.example 来访问(也就是说,非 https://foo.example 域无法通过跨源访问访问到该资源)

那我做为 bar.other 来说,我可能有两类资源,一类是静态的什么 js 啥的,第二类是 api 接口业务数据啥的

我想保护我自己。 所谓我可能要在一些有认证态(抱歉这是我造的词,不同网站可能不一样)的 http web api 加上响应头限制。 "Access-Control-Allow-Origin: https://foo.example:" 表示只能是 Origin 为 foo 的请求才能接收。 关键是这个响应已经发出去了啊, 我的保护意义何在呢?


所以如果我设置失误了,对于带 cookie 或者说认证状态的请求,我在响应头 "Access-Control-Allow-Origin: *"设置为这样,浏览器反而自动给我加了个保护,响应虽然发出去了, 在浏览器不解析这个响应报文数据。 ? 所以这是君子协定,靠浏览器的机制保护来约束?

可能这些才是我的疑惑,这些头部约束的目的和要解决的问题其实我是明白的,我其实想问它的控制机制和限制,


MDN 这一系列不能,只是为了安全考虑,如果我设置了会怎么样他没说,并且还是那句话,不同的网站,带身份凭证的请求各有不同,做为这种跨域约束协定,或者说我用某个头部做为认证,然后不小心设置了 Access-Control-Allow-Origin: * , 客户端怎么判断请求是否带身份凭证呢?怎么判断这个*应该不被接收呢?


```

在响应附带身份凭证的请求时:

服务器不能将 Access-Control-Allow-Origin 的值设为通配符(*),而应将其设置为特定的域,如:Access-Control-Allow-Origin: https://example.com
服务器不能将 Access-Control-Allow-Headers 的值设为通配符(*),而应将其设置为特定标头名称的列表,如:Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
服务器不能将 Access-Control-Allow-Methods 的值设为通配符(*),而应将其设置为特定请求方法名称的列表,如:Access-Control-Allow-Methods: POST, GET
服务器不能将 Access-Control-Expose-Headers 的值设为通配符(*),而应将其设置为特定标头名称的列表,如:Access-Control-Expose-Headers: Content-Encoding, Kuma-Revision
对于附带身份凭证的请求(通常是 Cookie ),

这是因为请求的标头中携带了 Cookie 信息,如果 Access-Control-Allow-Origin 的值为“*”,请求将会失败。而将 Access-Control-Allow-Origin 的值设置为 https://example.com ,则请求将成功执行。

另外,响应标头中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。
```


@GeruzoniAnsasu
@GeruzoniAnsasu
chinafengzhao
36 天前
@unco020511 其实第一个情况,要考虑到类似 jscdn 这种网站到期了被抢注了,这种域名被篡改了之类的,我做为黑客不一定要中间人攻击请求报文或响应报文,我可能攻击了类似 CDN 这种。 比如说我攻破大家都在用的 <script src="https://cdn.jsdelivr.net/npm/axios@1.6.2/dist/axios.min.js"></script> 假设这是我的恶意脚本,在这脚本里面去请求我的网站呢。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1153943

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX