2020-09-13 14:53:53
Cookie与会话安全详解
一、Cookie与会话的定义
Cookie定义:Cookie是Web服务端发送给用户浏览器的一小段数据,浏览器会存储这些数据,并在后续发往服务器的请求中带上它们。服务器可通过客户端发来的Cookie匹配服务器内存储的对应session,从而维持会话过程。
会话概念:
普遍概念:从用户登录直到退出期间,客户端与服务器的交互过程,会话的英文单词是session。
开发语言中的概念:服务器端存储的会话数据也称为session,一般前者基于后者实现。
二、第一方Cookie与第三方Cookie
第一方Cookie:用户当前访问的网站直接植入的Cookie,通常是网站用于正常功能的Cookie,如表示用户身份、记住用户的语言设置等。
第三方Cookie:
当用户访问一个网站时,如果这个网站加载了其他网站的资源,此时由其它网站植入的Cookie就称为第三方Cookie。
当不同的网站嵌入了同一个第三方网站资源时,用户访问这些网站时会带上相同的第三方Cookie去加载第三方资源。因此,第三方网站通过这个第三方Cookie就可以实现用户在不同网站的访问行为分析,从而实现更精准的广告投放。
三、Cookie属性
Domain属性:
用于指定Cookie在哪些域名中生效,即访问哪些域名时浏览器会发送这个Cookie。
也决定了哪些域名的网页可以通过JavaScript访问这个Cookie。
若域名前面带了一个点号“.”,则表示该Cookie对当前域名及其子域名都有效。
若不带点号,则仅访问当前域名时携带Cookie,但同时子域名的JavaScript代码可访问该Cookie。
若不指定Domain属性,则该Cookie为host-only-Cookie,即只对当前域名有效且子域名无法访问该Cookie。
注意:部分网站中,服务器端设置Cookie的Domain属性为父域名时会受到浏览器的拒绝(受到公共后缀列表影响)。
Domain属性不包含端口信息,即Cookie的域名隔离不受端口的限制。
Path属性:
用于指定Cookie的生效路径,即只有访问这个路径及其子路径时,浏览器才会携带这个Cookie。
若不设置该属性,则Path属性默认值就是当前页面所在的路径。
不能依赖Path属性来做安全隔离,因为在一个路径的页面可以使用iframe嵌入另一个路径的页面,而这两个页面是同源的,可以互访问DOM,从而读取另一个路径页面的Cookie。
Expires属性:
服务端可以通过该属性设置Cookie的有效期,浏览器会在这个Cookie到期后自动将其删除。
若没有指定expires属性,则该Cookie叫做“临时Cookie(也叫会话Cookie)”,当关闭浏览器后将自动删除该Cookie。但浏览器为了保证下次启动时用户体验的连续性,即使关闭浏览器也不会删除临时Cookie。
浏览器对每个站点有最大Cookie数量的限制,超限则会删除旧的Cookie(不管该Cookie到没到期),攻击者可利用这一点,通过植入多个Cookie,“挤掉”受害者正常的Cookie。
HTTPOnly属性:
让该Cookie只能用于HTTP/HTTPS传输,使得客户端JavaScript脚本无法读取Cookie,这在一定程度上减少了XSS漏洞带来的危害。
Secure属性:
给Cookie设置Secure属性后,该Cookie只会被包含在HTTPS请求中。
在客户端通过JavaScript设置Cookie或者在服务端通过set-cookie头来设置Cookie时,如果当前网站使用的是HTTP协议,则写入带Secure属性的Cookie就会失败。
SameSite属性:
服务端在Set-Cookie响应头中通过SameSite属性指示是否可以在跨站请求中发送该Cookie。
当Cookie没有指定SameSite属性时,现代浏览器的表现与SameSite=LAX时一致。
SameSite属性的三个值:
None:不做限制,但当SameSite被设置为None时,要求Cookie带上secure属性,即只能在HTTPS协议中发送该Cookie。
LAX:在普通的跨站请求中不发送Cookie,但是导航到其他网站时(如点击链接)会发送Cookie。
Strict:完全禁止在跨站请求中发送Cookie,由于过于严格,因此实际中使用较少。
SameSite还会影响跨站点Cookie的写入,跨站点Cookie的写入时,若脚本未指定SameSite属性,则浏览器默认SameSite=LAX,因此浏览器会拒绝跨站点写入该Cookie。

允许企业将多个网站定义成一个可信站点集合,称为First-Part Sets第一方站点集合。
网站服务器将可信站点集合定义在./well-known/first-part-set文件中,当一个网站的页面要请求另一个网站资源时,浏览器会检测这两个网站是否处于一个First-Part Sets中,如果是,那么带有SameParty属性的第三方Cookie将会被请求报文携带而不受SameSite属性的影响。
四、安全使用Cookie
Cookie前缀:
_Host-:如果一个Cookie的名称中有这个前缀,服务端通过set-cookie头设置Cookie或通过客户端脚本设置Cookie时,只有满足以下四个条件,浏览器才会接受这个Cookie:带有Secure属性、不包含Domain属性、Path属性值为“/”、当前为HTTPS连接。
_Secure-:如果一个Cookie的名称中有这个前缀,只有带有Secure属性且当前连接为HTTPS,浏览器才会接受这个Cookie,相对“_Host-”前缀而言,它是约束更少的弱化版本。
保密性与完整性:
Web服务器应当把Cookie当作不可信的外部输入数据,不能用Cookie数据来做关键的判断。
五、会话安全
会话ID的随机性:会话ID(sessionID)最基本的要求是随机性,也要足够长,防止枚举法。
过期与失效:超时机制应该在服务端实现,在时间到期后删除已存储的会话数据或标识该SessionID已失效。
绑定客户端:如果将会话与客户端绑定,即使攻击者窃取了SessionID,也无法在新的设备中登陆目标网站。
安全传输:现代Web应用基本上都是将SessionID写入Cookie中,并设置相应Cookie的安全属性(如开启HTTPOnly、Secure属性)。
客户端存储会话:使用JWT(JSON Web Token)机制用于会话管理,可以将会话信息完全存储在客户端,使服务端无状态。但已签发的会话Token无法吊销,因此需要在签发Token时加入有效期,并尽量使用短的有效期,可过短的有效期又会影响用户体验。签名使用的密钥的安全管理也很重要,一旦密钥泄露,攻击者就可冒充服务器端签发任意账号的JWT,使所有账号受到威胁。
综上所述,Cookie与会话安全是Web应用安全的重要组成部分。通过合理配置Cookie属性、加强会话管理以及采用安全传输机制等措施,可以有效提升Web应用的安全性。