CROS 同源问题的一些疑问

7 天前
 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

1946 次点击
所在节点    信息安全
26 条回复
lululau
7 天前
我理解所谓「同源策略」是用来防止 CSRF 的而不是 XSS 的吧
FlyaiF
7 天前
应该是为了防止浏览器里边进行一些假冒的网站,引导用户做一些用户意料外的操作吧
hurrytospring
7 天前
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
7 天前
这好比就是正规浏览器遵守的一个保护用户的规则而已吧。

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

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

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

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

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

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



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


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

协议或者说浏览器要求带这个头部之类的,他怎么判断这个是不是普通请求呢?有些请求里面有 cookie 不代表这是带凭证吧。
@GeruzoniAnsasu
unco020511
7 天前
1 的前提是你主动同意黑客这么干,或者说你就是黑客. 比如你主动在电脑中设置代理,并主动安装根证书到电脑,这样就你的 proxy 就可以随意修改 https 的请求和响应. 更进一步,你直接将你的电脑权限交给黑客.所以 1 已经超出了浏览器同源政策的范畴了
2 的话你可以理解是一个额外安全要求,附带身份凭证会认为是敏感信息,所以有一个额外的安全规定.
不过现在用户凭证很多都不用 cookie 之类的,你想放到哪都可以,比如额外搞个 header 附带 token.
浏览器是一个 httpClicent,当然知道你发送的请求细节,包括 https 的握手加密等细节都是浏览器去实现的,它自然知道,具体到开发中,就是设置 withCredentials 的值,你设置为 true 就认为你带了
chinafengzhao
7 天前
以 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
7 天前
@unco020511 其实第一个情况,要考虑到类似 jscdn 这种网站到期了被抢注了,这种域名被篡改了之类的,我做为黑客不一定要中间人攻击请求报文或响应报文,我可能攻击了类似 CDN 这种。 比如说我攻破大家都在用的 <script src="https://cdn.jsdelivr.net/npm/axios@1.6.2/dist/axios.min.js"></script> 假设这是我的恶意脚本,在这脚本里面去请求我的网站呢。

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

https://ex.noerr.eu.org/t/1153943

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

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

© 2021 V2EX