一、“记住我”的功能不安全的地方
登录之后,让我们来看看cookies
如果你没勾选“记住我”的话,这些要命的信息是不会被cookie记录的,所以那个功能原本也只是单纯为了方便用户再访的。在图中,我的邮箱地址是赤裸裸的,但密码并非明文。然而不要高兴得太早,对着那串似乎坚不可摧的加密字符定睛一看……咦?等一下,这不是Base64编码吗!关于Base64编码,这是一种可以被完整解码的编码,这意味着你可以随便去哪个编码转换网站比如base64。
并不是所有人都把Base64当做“加密”,虽说它确实是一种合理代替ASCII的方法,但事实上这种编码的密码仅仅在刚一进入浏览器后就会立即转变为明文。你可能会质疑道 - 这能有多大问题?无论如何它只是存储在自己的浏览器里,它能怎样?那到底黑客能不能得到它呢?
这些存储在Cookie中的密码并没有被标记成HttpOnly,你可以在右边的cookie列表中看到。这意味着,客户端脚本可以访问这些cookies。缺少了HttpOnly属性或许是一时马虎,但问题的核心在于存储在cookie中的密码会很容易地通过其他途径疏漏出去。
还有一个更根本的原因,为什么这些网站会同时在这点上疏忽大意,尽管他们都在保护自己客户在其网站上使用的凭据。每当上述网站的客户勾选了“记住我”功能并向网站上发出请求时,当他们的用户名和密码被网站发送到他们的邮箱时,当他们操作eBay或网银时。要么密码是明文,要么可以通过客户端脚本获取,总之密码总会一丝不挂的躺在浏览器里。大量的人有密码复用(通用)的习惯 。我不得不说,当我们应对那些用户凭据威胁的时候,需要实施的保护措施要远远超过网站本身。
二、如何安全实现“记住我”的功能
1、寻找身份验证Cookie的时限部分
“记住我”功能可以简单地归结为,它控制了cookie的时限并且决定某个人能够持续登录多久。
ASP.NET默认使用一个会话cookie,或者换句话说,一个cookie,而且没有一个明确的截止日期,因此将在浏览器关闭时强行过期。这是一种方法,另一种是直接置入短保质期,即使浏览器继续使用该cookie,用户也将被自动注销。当然,你也可以在服务器上控制这种行为,你也可以让身份验证cookie的时限不断延长,如果系统正在积极使用由服务器响应增加的时限。
只要保持这个验证cookie有效,特定的人就会被记住。那多久的时效才合适呢?上面的例子中默认为2天,但这对于合法的使用者显然有些过短。持续时间较短,意味着更少的风险,但更多的不便,持续时间较长,使得它更容易为用户增加潜在的风险。让我们更进一步的看看这个风险。
2、长期认证状态的利用
当在被认证之前,你的会话无法被劫持。例如有的网站的cookie将在6个月后到期,与此同时它没有HTTP only的标记,这样一来他们网站的XSS漏洞可以为攻击者提供半年的时间去获取并使用用户的凭证。同样的情况,如果时限为1个月,他们仍会有一些严重的漏洞,但上述攻击的机会实实在在地得到了削减。
另一方面,在他们暴露着ELMAH日志的情况下,依然有一系列的重大疏漏,但除非有人在一周前已经用“记住我”登录了网站,并且触发了那个默认配置的漏洞,否则凭据不会被泄露。如果你想找个网站自己试试看的话,就算是一个你已经登录过的网站,也可以看到存在时限风险的cookie。
所以说一切有关身份验证的cookie如果想要保护好用户凭据的话,HttpOnly的安全属性是和严谨的安全态度必须的。虽然所有经典的劫持威胁仍然存在,不过,解决这些cookie上的问题也是绝不容忽视的。
归根结底,这是一个权衡,需要考虑的因素如攻击者要取得的数据的价值,在加强验证安全性时对于用户使用的便捷性和网站安全配置所造成的负面影响。例如,Facebook中存在着一些非常有用的社会性的用户数据,而用户又非常希望无延时般的响应速度,在此之上他们还对自己的账户安全上进行了大笔的投资。而对于AFD网,在持有用户个人身份数据以及财务信息的同时,提供了用户所要求的安全验证服务,能看出用户本身也是有相关安全意识的。他们有着迥然不同的风险,这两个网站对于身份验证cookie的时限策略应该是完全不同的。
3、强化
或许会觉得AUTH cookie很无解,有关安全性的东西总会有一种更好的解决方案,但这是有代价的,安全性取决于你愿意付出的的时间、金钱、便利性,而且也总会有人告诉你,你做错了!让我们来看看关于使用AUTH cookie时限的一些可能的加强方法。
对于一个长期有效的AUTH cookie,问题在于他们需要有效地保持用户身份的验证和面对如CSRF或clickjacking等攻击风险。当然,还有很多需要利用长期cookie的风险并没有列出,但这并不影响围绕防范方法的讨论。还有一点就是当一个专用cookie为用户在服务器上提供过有效认证之后,在返回时它还可以重新开启另一个认证会话。虽然最初的会话会迅速到期,但关键是重启的新会话,它会因为用户勾选了“记住我”并再次登录而进行另外的验证。
一种验证方式包括利用用户的IP地址/用户代理/其他显著特点来限制“记住我”的cookie。这能提供一些对cookie劫持的防御。当然,要在合法使用的情况下进行这些变更。特别是在移动网络中这类的情况并不少见——用不同的IP回访一个网站。你的ISP不一定总会提供静态的IP地址。至于用户代理,还有浏览器差异,如Chrome和Firefox的更新简直恍如隔日。然而除非你刻意去挑选某些优质的代理,否则使用代理将是一个危险的做法。
还有一种程序化的手段,就是保持“记住我”cookie和身份验证cookie的分离,并使用前者重新验证用户的身份,但要额外施加一些限制。实际情况是,某个身份的自动认证状态的过程,一定会遵循安全模型。缓和措施的结果就是,它会在自动重新验证之前,向用户再次索要凭据。这并非创新之举,你或许会在进行例如网银汇款时遇到过此类功能。在这里,我们说身份验证的用户面临的风险很大,因为这种方式很容易被劫持和欺骗。
至于其他加强方法,我们可以在“记住我”cookie被使用后进行复位。这也等于让它在服务器端无效,而需要一个独特且持久的cookie值,例如存在于数据库和cookie间的一个随机数。这样有利于确保cookie不会被攻击者用下面的方式获得。在这里的文章中,作者谈论了一些关于这类模式的缓解方法。但你需要付出一些额外的工作,并在某种程度上给正常的用户带来不便(例如用户无法跨越多个电脑使用并“记住”自己的凭据)。
最后一件值得提一句的是,同一帐户下的管理原则,它需要我们去关注并且和“记住我”功能有关。例如,允许单一用户的多个会话同时验证?或者用户一旦更改了密码要不要将会话断开?管理员可不可以结束验证会话?出现了各种各样的问题,不过这里要讨论的仅仅是关于如何复原。
三、什么时候不该用“记住我”功能?(以及一些替代功能)
有时候,允许一个经过认证的用户保持认证状态很长一段时间是毫无意义的。例如银行,在常规的使用情况下,当你想图省事非要进行自动登录时,在你走人以后留在那里的是一个未登出的浏览器,风险多大不用我说了吧。