《白帽子讲Web安全》第四章学习笔记(Cookie)
Cookie和会话安全
Cookie和会话简介
Cookie是Web服务器发给用户的一小段数据,浏览器会存储这些数据,并在后续发往浏览器的请求中带上它们。
因为HTTP协议本身是无状态的 ,底层的TCP连接会断开,用户的IP地址也会发生变化,但是Web应用的服务端需要记住每个访问者的状态,例如登录一次后就无需再登录,所以这个过程中就需要存储一份数据来标识用户。我们可以通过Cookie将用户标识存储再客户端,但此时用户可以查看和篡改这些数据。
因此,安全起见,可以将Cookie中的数据加密
或者将数据存储在服务端
,为用户随机分配一个ID,在客户端仅存储这个ID,让用户带上ID来访问服务器。此过程中,服务器存储的这份数据称为Session,客户的随机ID为SessionID。
会话
一般指从用户登录直到退出期间客户端与服务端的交互过程。
第一方Cookie和第三方Cookie
第一方Cookie是指用户当前访问的网站直接植入的Cookie,通常是网站用于正常功能的Cookie,比如标识用户身份、记住用户的语言设置等。
当用户访问一个网站时,如果这个网站加载了其他网站的资源,此时由其他网站植入的Cookie称为第三方Cookie(比如广告)
当不同的网站嵌入了同一个第三方网站资源时,用户访问这些网站时会带上相同的第三方Cookie去加载第三方资源,所以第三方网站通过这个第三方Cookie就可以实现用户在不同网站的访问行为分析,实现更精准的广告 投放。
所有浏览器都会接受第一方Cookie,但是浏览器的隐私策略可能会阻止部分第三方Cookie。
Cookie属性
Domain属性
Domain属性用于指定Cookie在哪些域名中生效
,即访问哪些域名时浏览器会发送这个Cookie,该属性也决定了哪些域名的网页可以通过JavaScript访问这个Cookie。如果域名前面带一个点号“ .”表示该Cookie对当前域名及其子域名都有效,浏览器访问这些子域名时都会带上这个Cookie;如果域名前不带点号,表示Cookie仅对当前域名有效。
如果在Set-Cookie中不指定Domain属性,Cookie的生效范围仅限于当前域名(即请求中Host头指定的域名),它被称为Host-Only Cookie。
Cookie的域名隔离不受端口限制。
Path属性
Path指定Cookie的生效路径
,只有访问这个路径或其子路径时,浏览器才会发送这个Cookie。如不设置,Path的默认值为当前页面所在路径。
但不能依赖 Path来做安全隔离,因为可以通过iframe
将一个路径的页面嵌入到另一个路径的页面,而这两个页面是同源的,所以它们之间的DOM可以互访问,一个路径的页面可以读取另一路径页面的Cookie。
Expires 属性
服务端可以通过Expires属性来设置Cookie的有效期
,浏览器会在这个Cookie到期后自动将其删除。没有指定Expires属性的Cookie叫“临时Cookie”,关闭浏览器会自动删除。
浏览器对每个站点有最大Cookie数量的限制,超过这个限制会删除旧的Cookie。所以如果存在可以向受害者植入Cookie的漏洞(如CRLF注入漏洞),攻击者可以植入多个Cookie,导致 受害者的正常Cookie被挤掉。
HttpOnly属性
HttpOnly属性的作用是让Cookie只能用于HTTP/HTTPS传输,客户端JavaScript无法读取它,从而在一定程度上减少XSS漏洞带来的危害。
Secure属性
给Cookie设置Secure属性后,该Cookie只会在HTTPS请求中被发送给服务器,非加密的HTTP请求是不会发送该Cookie的,确保了它不会再网络中以明文传输。
同时如果客户通过JavaScript设置Cookie,或者在服务端通过Set-Cookie头来设置Cookie时,如果当前网站用的时HTTP协议,写入带Secure的Cookie会失败。
SameSite属性
SameSite是一个新的安全属性,服务端在Set-Cookie响应头中通过SameSite属性指示是否可以在跨站请求中发送该Cookie,即它能不能作为第三方Cookie,这个属性有3种值。
None
不做限制,任何场景下都会发送Cookie,但要求Cookie带上Secure属性,即只能在HTTPS协议中发送。(与浏览器不支持SameSite效果相同)LAX
在普通的跨站请求中都不发送Cookie,但是导航到其他网站时(如点击链接)会发送Cookie。另外,在跨站点提交表单的场景中,只有GET方法提交的表单会带Cookie,POST方法不行。(与浏览器不指定SameSite效果相同默认
)Strict
SameSite属性为Strict表示严格模式,即完全禁止在跨站请求中发送Cookie,即使点击站外链接也不会发送Cookie,只有当请求的站点与浏览器地址栏URL中的域名属于同一站点时,才会发送Cookie。
SameParty属性
将多个网站定义成一个可信站点集合
,称为First-Party Sets(第一方站点集合)。可以给运营了多个站点的企业带来方便。
网站将可信站点集合定义在/.well-known/first-party-set 文件中,当一个网站的页面要请求另一个网站资源时,浏览器会检测这两个网站是否同处一个First-Party Sets,如果是,那么带有SameParty属性的第三方Cookie也会被带上。
安全使用Cookie
正确设置属性值
在HTTPS应用中,应该对关键的Cookie设置Secure属性,确保它只有在加密的网络连接中传输。
如果没有必要让子域名读取Cookie,在植入Cookie时就不要设置Domain属性,让Cookie只有当前域名可读取。
对重要的Cookie设置HttpOnly属性。
如果网站不需要被其他站点引用,对于与会话有关的Cookie,建议将SameSite属性设置为LAX。
Cookie前缀
__Host-
服务端通过Set-Cookie设置Cookie头设置Cookie,或者前端脚本通过document.cookie属性设置Cookie时,要满足以下四个条件:带有Secure属性
不包含Domain值
Patn属性为“/”
当前为HTTPS连接
__Secure-
要带Secure属性且当前为HTTPS连接。
保密性与安全性
由于Cookie对客户没有保密性,要把Cookie当作不可信的外部输入数据
会话安全
会话管理
会话ID的随机性
过期与失效
绑定客户端
与浏览器User-Agent绑定,与访问者的IP地址绑定安全传输
现代Web应用基本上都将SessionID写入Cookie中,所以设置相应Cookie的安全属性相当重要,大多数情况下建议开启HttpOnly和Secure属性客户端存储会话
也有一些应用会将会话存储在客户端如JWT用于会话管理
JWT本质上是带签名的JSON数据,有必要的情况下也可以对它加密。
固定会话攻击
在一些场景中攻击者可以诱导用户使用攻击者指定的SessionID,当受害者登录成功后,攻击者就拥有了受害者在目标网址的身份。这就叫固定会话攻击。
在多个子域名应用的场景中,一个恶意的子域名应用可以设置一个在其他子域名也生效的Cookie,这样恶意应用就可以设置受害者在其他应用的SessionID。类似的场景还有同一个域名在不同端口运行了多个应用,或者在一个域名的不同路径下运行了不同的应用,恶意应用都可以写入一个在其他应用也有效的Cookie。
在存在XSS漏洞或CRLF注入漏洞的应用中,攻击者也可能给受害者植入特定的Cookie来实施固定会话攻击。
所以在用户的登录状态发生变化后,服务端应该为用户生成一个新的SessionID,这样就杜绝了固定会话攻击。