Cookie与Passport安全

对于web系统而言,因为HTTP协议无状态的特性,用户登陆时须要服务端生成通行证返回给浏览器。浏览器保存该通行证并在接下来的请求中携带该通行证。一般来说,web系统使用http cookie来保存和传输通行证。本文介绍http cookie的原理、特性、并分析用其保存通行证可能遇到的安全问题。javascript

本文假设使用cookie的客户端是浏览器,虽然还有其它客户端也使用cookie,但普通用户使用更多的仍是浏览器。html

一种Http状态管理机制,最先由Lou Montulli发明于1994年,最新的标准是2011年发布的RFC 6265 - HTTP State Management Mechanism。由于保存信息到客户端的本质,也有系统用cookie来缓存信息,但这并非Http Cookie的主要用途。java

Cookie既指整个状态保存机制,也指用户保存状态的数据自己,由String类型的name和value以及若干属性组成。追根溯源,其名字来源于fortune cookie,一种内含写有幸运文字小纸条的饼干。git

Cookie保存在哪,如何生成又怎样传输?

Cookie由服务端生成,保存在浏览器。经过两个Http Header:Set-Cookie和Cookie进行传输。Set-Cookie Header用于服务端传输登陆通行证等cookie键值对及属性给浏览器,浏览器收到并验证合法性后会作相应保存。Cookie Header用于浏览器传递cookie键值对给服务端,服务端依次来鉴别用户身份等状态信息。github

RFC6265定义了Cookie的一些属性,包含Expires、Max-Age、Domain、Path、Secure、HttpOnly。也有一些还没定义到RFC,但已经实际应用的属性,好比SameSite。Cookie写时有属性读时无属性,属性仅在设置时即Set-Cookie Header中指定,浏览器依此来决定是否接受该cookie如何使用该cookie,而一旦浏览器决定了将cookie放到Cookie Header中传递到服务端,那么浏览器不会传递更多的的信息到服务端,只会传递键值对name和value。web

HttpCookie

不少浏览器会提供读Cookie和写Cookie的api给运行在其上Javascript脚本使用,一般的api是操做docment.cookie:算法

document.cookie=“SID=31d4d; domain=example.com; path=/;”;

说说Domain和Path这两个属性

Domain、Path、Name三者惟一肯定一个cookie。其它属性仅用做读写时的权限控制,不做为cookie标识。在浏览器在使用cookie时:sql

  • 不区分Http/Https
  • 不区分端口号

这相比浏览器同源策略更加宽松,带来不少安全问题。chrome

Domain是向上通配的:数据库

  • 写入(Set-Cookie)访问www.example.com
Set-Cookie: sid1=a; domain=example.com; path=/;            接受
    Set-Cookie: sid2=b; domain=www.example.com; path=/;        接受
    Set-Cookie: sid3=c; domain=pay.example.com; path=/;        拒绝
  • 读取(Cookie)
访问pay.example.com
        Cookie: sid1=a
        
    访问www.example.com
        Cookie: sid1=a; sid2=b;

不少系统写cookie,习惯在域名前加一个点,写成.example.com,觉得这么写才是通配的,其实这个点是多余的,没有必要的。

Path是向下通配的:

  • 写入(Set-Cookie)
Set‐Cookie: sid1=a; domain=example.com; path=/;
    Set‐Cookie: sid2=b; domain=example.com; path=/test/;
  • 读取(Cookie)
访问http://example.com/
        Cookie: sid1=a;
    
    访问http://example.com/test/
        Cookie: sid1=a; sid2=b

Cookie的有效期过长致使通行证泄露

这两个属性指定cookie有效期。不指定有效期时,cookie默认为当前session有效,当前session有效指关闭浏览器时cookie失效。

Cookie的有效期过长可能致使通行证泄露。好比用户使用了公用电脑,关闭浏览器时,没有点击注销。这样Cookie就留存在这台电脑上,其它人只需打开浏览器便可获取其在网站上的cookie。

通常保存通行证的cookie应该设置为session有效的cookie,并在用户选择记住登陆状态时,提醒用户,不要再公用电脑上作这样的勾选。

明文传输的HTTP流量

HTTP明文传输数据的特性,使得攻击者可从网路上抓包获取Cookie。

解决方案:

  • 服务端使用HTTPS
  • 指定cookie的secure属性,该属性使cookie只能在HTTPS请求中带出。

利用XSS漏洞读取保存在cookie的通行证

假如网站存在XSS漏洞,那么恶意JS可直接读取Cookie中的通行证。能够经过指定Cookie的HttpOnly属性。对于指定了HttpOnly的Cookie,浏览器会拒绝JS读写。

XSS仍有可能利用服务端漏洞获取cookie:
- 服务端有可能在请求的正常响应中包含通行证。不要笑,这真的有,尤为如今不少公司app和web共用一套后台;
- 服务端可能有漏洞致使cookie包含在请求响应中,从而被窃取。好比:Apache CEV-2012-005

因此HttpOnly不是银弹,XSS也有不少其它的危害。但至少,HttpOnly能够避免通行证在浏览器被JS直接读取。

利用XSS漏洞写cookie

  • 使用户退登

保存了通行证的cookie由于是HttpOnly,因此XSS没法读取。但XSS仍是能够写Cookie,因为domain、path、name三者才惟一标识一个cookie,XSS能够写一个跟通行证cookie name相同,但domain或path不一样的cookie。

这样当浏览器发送请求给服务端时,服务端就会收到两个相同name的cookie。由于cookie读时无属性,因此服务端无从判断哪个才是正确的。这样会使用哪个cookie,就要看具体web server的实现,多是第一个也多是第二个。

这样经过写cookie,XSS能够轻易地使已登陆用户退登。

  • 更危险的状况,Cookie替换攻击

恶意JS可针对特定的域名和path写入一个攻击者的cookie通行证。好比针对某电商网站的余额充值domain和path,写入攻击者的通行证。该攻击者cookie在用户正常购物的请求中不会带出,当用户充值时会带出,从而使用户充值到了攻击者的帐号。

不安全的公共wifi

对于HTTP,公共wifi可劫持用户全部的流量,窃取cookie通行证天然不在话下。

对于HTTPS,由于能够在DNS上作手脚,能够在路由器上截取和篡改流量,在公共wifi上很容易诱导用户发出到网站的HTTP请求,几遍该网站是全站HTTPS也是如此。

所以,对于XSS写cookie的危害,公共wifi都能作到。并且能力更强,危害更大。

对于设置了secure属性的cookie,虽然不会在http请求中带出,但却可被http请求的Cookie设置覆盖。所以,设置了secure也不安全。

Although seemingly useful for protecting cookies from active network
attackers, the Secure attribute protects only the cookie's
confidentiality. An active network attacker can overwrite Secure
cookies from an insecure channel, disrupting their integrity
---- from RFC 6265

HSTS

公共wifi的危害,有一个关键点,就是诱导用户对指定网站发出HTTP请求。这一点经过HSTS - HTTP Strict Transport Security能够避免。

HSTS经过设置strict‐transport‐security头,来告知浏览器,对当前域名以及全部子域名,都只使用HTTPS访问。

让浏览器对当前域名及子域名,强制进行HTTPS访问:

strict‐transport‐security: max‐age=15552000;includeSubDomains;

但HSTS在现实中难以被利用。由于:

  • 囿于cookie的通配特性,必须对整个域名部署HSTS才能生效;
  • 浏览器并不是全支持这个特性。IE11+才开始支持;

因此,真正全站部署HSTS的网站,少之又少。

利用cookie大小和数量的限制来破坏安全

o At least 4096 bytes per cookie (as measured by the sum of the
length of the cookie's name, value, and attributes).
o At least 50 cookies per domain.
o At least 3000 cookies total.
---- From RFC 6265

  • Cookie的大小和数量是有限制的;
  • 每一个浏览器,每种Web Server,限制均可能不同;
  • 超出限制的行为,是未定义的。

设置超大cookie,超多cookie,都是典型的攻击手段。上文提到的Apache CEV-2012-005漏洞,便是利用了Apache对Cookie大小的限制。

利用csrf漏洞偷用通行证

在访问恶意网站时,网站的页面代码中,可能包含到你银行帐号或是其它什么帐号的请求。因为这时浏览器会自动带出到相应域名的cookie,因此用户的登陆通行证,就很容易被恶意网站偷用。

csrf

这个问题,能够经过设置Cookie的SameSite属性来解决。设置了SameSite属性的cookie,只会在当前正在访问(浏览器地址栏)的域名与cookie的domain可匹配时,才会带出。

  • 在设置SameSite时,能够指定严格仍是不严格。在不严格的状况下,若是请求会致使浏览器地址栏发生变化,那么cookie也是容许带出的;
  • SameSite没有包含在RFC 6265中,所以还不是标准。但Chrome 51(发布于2016年8月)已经支持了这个属性。

以下截图,是Chrome支持的cookie属性:

Chrome Cookie

读取浏览器保存在硬盘上的cookie

有人会说,cookie不就是存放在硬盘,我直接从硬盘上窃取不能够吗?

答案是能够。好比Chrome的cookie就存放在目录:C:\Users<username>\AppData\Local\Google\Chrome\User Data\Default\下,是一个sqllite的数据库文件,虽然cookie内容都进行了加密,但也是能够破解的。

只是,当你攻破一个用户的电脑,破解了chrome的加密算法,最终只是窃取到了一个用户的登陆凭证而已。这种攻击,性价比很低。

举个例子

Github推出的github pages功能,一开始的时候使用的是github.com主站域名,后来由于上面提到的cookie安全问题,不得不为github pages单独启动了github.io域名。

具体可看Github的官方blog,里面提到了上面部分的cookie安全问题。blog连接:Yummy Cookies across Domains

总结

  • Cookie从机制上就有安全问题,使用时要当心再当心;
  • 对于一些增强安全的Cookie属性,要尽可能在系统早期实施。越晚实施,代价越大,实施难度越高;
  • 公共wifi不安全,即使网站使用了https,公共wifi也不安全。当离开一个公共wifi时,清除这段时间浏览器产生的cookie!

Reference

相关文章
相关标签/搜索