跨站和SameSite


跨站和SameSite

Cookie 的 SameSite 属性可以让 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。

SameSite 属性值可以有下面三种值:

Strict:仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL完全一致。
Lax:允许部分第三方请求携带 Cookie
None:无论是否跨站都会发送 Cookie
之前默认是 None,Chrome80 后默认是 Lax。

跨域和跨站

跨域
跨域对应的是同域,同域即是浏览器的同源策略,这里不单单是指相同域名,域名、协议、端口号必须完全一致,才属于同源。

跨域主要是针对请求的。如果跨域,浏览器会在控制台提示类似的Error。

跨站
跨站对应的是同站,也可以称呼叫做第一方(同站)或者第三方(跨站)。同源策略作为浏览器的安全基石,其「同源」判断是比较严格的。相对而言,Cookie中的「同站」判断就比较宽松:只要两个 URL 的 eTLD+1 相同即可,不需要考虑协议和端口。其中,eTLD 表示有效顶级域名,例如,.com、.http://co.uk、.http://github.io 等。eTLD+1 则表示,有效顶级域名+二级域名,例如 taobao.com 等。

Public Suffix List
假设这样的情况:

  1. a.jzplp.com与b.jzplp.com 实际属于同站

  2. jzplp.com.cn与other.com.cn 实际属于跨站

  3. jzplp.github.io与other.github.io 实际属于跨站

第一个属于同站。看第二个例子,com.cn是我们国家颁布的二级域名并不是指的某一个网站。显然这种域名后缀,并不能认为是同站。除了我国,还有其他国家和组织也会公布这种二级甚至更高级的域名。再看第三个例子,是Github提供的网站域名。使用github.io后缀的网站,显然也不能认为是同站。

因此,仅仅通过网址格式匹配,是无法判断是否同站的。因此,浏览器会维护一个列表:Public Suffix List。列表里面记录了这些需要特殊匹配的域名后缀,比如上面提到的com.cn与github.io等等,这个叫做有效顶级域名,eTLD。在遇到一个域名时,会首先匹配列表中的后缀,再把eTLD+1个字段相同表示为同站,不同表示为非同站。

例如 列表中的域名后缀为com.cn,那么eTLD+1个字段表示为jzplp.com.cn。那么a.jzplp.com.cn与b.jzplp.com.cn属于同站, jzplp.com.cn与other.com.cn属于跨站。

Public Suffix List列表的内容。这个列表会随着浏览器的更新而更新。

经实测,协议不同也会跨站。我是在 http 网页内用 iframe 嵌套 https 网页, 2个网页的 eTLD+1 是相同的。iframe 里的第三方网页,登录时设置 cookie 失败,接下去的请求也没有发送 cookie。

跨站一定跨域,跨域不一定跨站。

改变
接下来看下从 None 改成 Lax 到底影响了哪些地方的 Cookies 的发送?

请求类型 实例 Strict Lax None
链接 <a href="..."></a> 不发送 发送Cookie 发送Cookie
预加载 <link rel="prerender" href="..."/> 不发送 发送Cookie 发送Cookie
get表单 <form method="GET" action=""> 不发送 发送Cookie 发送Cookie
post表单 <form method="POST" action=""> 不发送 不发送 发送Cookie
iframe <iframe src=""></iframe> 不发送 不发送 发送Cookie
AJAX $.get(“…”) 不发送 不发送 发送Cookie
image <img src="/2024/10/26/52081.htmlundefined" > 不发送 不发送 发送Cookie

可以看出,对大部分 web 应用而言,Post 表单,iframe,AJAX,Image 这四种情况从以前的跨站会发送三方 Cookie,变成了不发送。

Post表单:应该的,学 CSRF 总会举表单的例子。
iframe:iframe 嵌入的 web 应用有很多是跨站的,都会受到影响。
AJAX:可能会影响部分前端取值的行为和结果。
Image:图片一般放 CDN,大部分情况不需要 Cookie,故影响有限。但如果引用了需要鉴权的图片,可能会受到影响。
除了这些还有 script 的方式,这种方式也不会发送 Cookie。

解决
解决方案就是设置 SameSite 为 none。

不过也会有两点要注意的地方:

1:HTTP 接口不支持 SameSite=none。
如果你想加 SameSite=none 属性,那么该 Cookie 就必须同时加上 Secure 属性,表示只有在 HTTPS 协议下该 Cookie 才会被发送。
服务端和js都可以这么设置。
2:需要 UA 检测,部分浏览器不能加 SameSite=none。
IOS 12 的 Safari 以及老版本的一些 Chrome 会把 SameSite=none 识别成 SameSite=Strict,所以服务端必须在下发 Set-Cookie 响应头时进行 User-Agent 检测,对这些浏览器不下发 SameSite=none 属性

CSRF

攻击者会导致受害者用户无意中执行操作。例如,这可能是为了更改其帐户的电子邮件地址、更改其密码或进行资金转账

CSRF 攻击成为可能,必须满足三个关键条件

相关操作:例如修改其他用户的权限或对用户特定数据的任何操作(例如更改用户自己的密码

基于 Cookie 的会话处理:应用程序仅依赖会话 Cookie 来识别发出请求的用户。没有其他机制可用于跟踪会话或验证用户请求

没有不可预测的请求参数:执行该操作的请求不包含攻击者无法确定或猜测其值的任何参数

最常见防御措施

CSRF 令牌是由服务器端应用程序生成并与客户端共享的唯一、秘密且不可预测的值。

SameSite 是一种浏览器安全机制,用于确定何时将网站的 Cookie 包含在来自其他网站的请求中。自 2021 年以来,Chrome 默认强制实施 SameSite:Lax 限制

基于 Referer 的验证 - 某些应用程序使用 HTTP Referer 标头来尝试防御 CSRF 攻击,通常是通过验证请求是否来自应用程序自己的域

XSS 和 CSRF 有什么区别?

XSS允许攻击者在受害者用户的浏览器中执行任意 JavaScript。

CSRF允许攻击者诱使受害者用户执行他们不打算执行的操作

CSRF 可以被描述为“单向”漏洞;XSS 是“双向”的,因为攻击者注入的脚本可以发出任意请求、读取响应并将数据泄露到攻击者选择的外部域

CSRF 令牌验证中的常见缺陷

验证取决于请求方法:某些应用程序在请求使用 POST 方法时正确验证令牌,但在使用 GET 方法时跳过验证

**验证取决于令牌的存在:**某些应用程序会在令牌存在时正确验证令牌,但如果省略令牌,则会跳过验证。

令牌未绑定到用户会话:某些应用程序不验证令牌是否与发出请求的用户属于同一会话。相反,应用程序维护它已颁发的令牌的全局池,并接受此池中显示的任何令牌

令牌与非会话 Cookie 绑定:某些应用程序确实将 CSRF 令牌绑定到 Cookie,但不绑定到用于跟踪会话的同一 Cookie。当应用程序使用两个不同的框架时,这很容易发生,一个用于会话处理,另一个用于 CSRF 保护,它们没有集成在一起

令牌只是在 cookie 中复制:某些应用程序不维护已颁发令牌的任何服务器端记录,而是在 Cookie 和请求参数中复制每个令牌。验证后续请求时,应用程序只需验证 request 参数中提交的令牌是否与 Cookie 中提交的值匹配。

域名后缀,亦被称为顶级域名(Top Level Domain),是指代表一个域名类型的符号。 不同后缀的域名有不同的含义。域名共分为两类:**国别域名(ccTLD),例如中国的.cn、美国的.us俄罗斯的.ru、以及国际通用域名**(gTLD),例如.com.xyz.top.wangpub.xin.net等1000多种

https://app.example.com:443

  • https://为schema
  • .com为TLD
  • .example.com为TLD+1
  • TLD+1和schema统称为站site
  • https://app.example.com:443整体称为origin
请求方 请求 同站点? 同源?
https://example.com https://example.com 是的 是的
https://app.example.com https://intranet.example.com 是的 否:域名不匹配
https://example.com https://example.com:8080 是的 否:端口不匹配
https://example.com https://example.co.uk 否:不匹配的 eTLD 否:域名不匹配
https://example.com http://example.com 否:不匹配的方案 否:不匹配的方

绕过基于 Referer 的 CSRF 防御
Referer 标头
HTTP Referer 标头(在 HTTP 规范中无意中拼写错误)是一个可选的请求标头,其中包含链接到所请求资源的网页的 URL。它通常由浏览器在用户触发 HTTP 请求时自动添加,包括通过单击链接或提交表单。存在各种方法,允许链接页面保留或修改 header 的值。这样做通常是出于隐私原因
1:如果省略标头,则跳过验证
<meta name="referrer" content="never">
2:如果应用程序验证 中的域是否以预期值开头,则攻击者可以将其作为自己域的子域,如果应用程序只是验证 是否包含自己的域名,则攻击者可以将所需的值放在 URL 中的其他位置,http://attacker-website.com/csrf-attack?vulnerable-website.com

可确保发送完整的 URL,包括查询字符串。Referrer-Policy: unsafe-urlReferrer

防止 CSRF 漏洞

使用 CSRF 令牌必须满足以下条件:

  • 高熵不可预测,就像一般的会话令牌一样。
  • 绑定到用户的会话。
  • 在执行相关操作之前,在每种情况下都经过严格验证

使用严格的 SameSite Cookie 限制

警惕跨域、同一站点的攻击


文章作者: 读序
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 读序 !
  目录