大家还记得四月份的 OpenSSL Heartbleed 事件吗?当时除了网站本身以外,受害最严重的就属 VPN Server 了。国内外不少骇客不眠不休利用 Heartbleed 漏洞窃取 VPN Server 的管理者 Session Cookie,运气好的话就可以直接登入大企业的内网。
但是,其实这样的风险是可以避免的,今天我们以开发者的角度来谈谈 Session 的攻击与防护。
在谈 Session 之前,我们要先了解 Cookie。你知道网站是如何辨识我们的身份吗?为什幺我们输入完帐号密码之后,网站就知道我们是谁呢?就是利用 Cookie。Cookie 是网站在浏览器中存放的资料,内容包括使用者在网站上的偏好设定、或者是登入的 Session ID。网站利用 Session ID 来辨认访客的身份。
Cookie 既然存放在 Client 端,那就有被窃取的风险。例如透过 Cross-Site Scripting(跨站脚本攻击,又称 XSS),攻击者可以轻易窃取受害者的 Cookie。如果 Cookie 被偷走了,你的身份就被窃取了。
我们可以用一个譬喻来表示:你加入了一个秘密俱乐部,填写完会员资料后,得到了一张会员卡。之后只要凭这张会员卡,就可以进入这个俱乐部。但是隔天,你的会员卡掉了。捡走你会员卡的人,就可以用你的会员卡进入这个秘密俱乐部,因为会员卡上没有你的照片或是其他足以辨识身分的资讯。这就像是一个会员网站,我们申请了一个帐号(填写会员资料加入俱乐部),输入帐号密码登入之后,得到一组 Cookie,其中有 Session ID 来辨识你的身分(透过会员卡来辨识身分)。今天如果 Cookie 被偷走了(会员卡被捡走了),别人就可以用你的帐号来登入网站(别人用你的会员卡进入俱乐部)。
Session 攻击手法有三种:
我们以下一一介绍。
1. Session Prediction (猜测 Session ID)
Session ID 如同我们前面所说的,就如同是会员卡的编号。只要知道 Session ID,就可以成为这个使用者。如果 Session ID 的长度、複杂度、杂乱度不够,就能够被攻击者猜测。攻击者只要写程式不断暴力计算 Session ID,就有机会得到有效的 Session ID 而窃取使用者帐号。
分析 Session ID 的工具可以用以下几种
观察 Session ID 的乱数分布,可以了解是否能够推出规律、猜测有效的 Session ID。
Ref: http://programming4.us/security/3950.aspx
防护措施
使用 Session ID 分析程式进行分析,评估是否无法被预测。如果没有 100% 的把握自己撰写的 Session ID 产生机制是安全的,不妨使用内建的 Session ID 产生 function,通常都有一定程度的安全。
2. Session Hijacking (窃取 Session ID)
窃取 Session ID 是最常见的攻击手法。攻击者可以利用多种方式窃取 Cookie 获取 Session ID:
窃取利用的方式如下图:
受害者已经登入网站伺服器,并且取得 Session ID,在连线过程中攻击者用窃听的方式获取受害者 Session ID。
攻击者直接使用窃取到的 Session ID 送至伺服器,伪造受害者身分。若伺服器没有检查 Session ID 的使用者身分,则可以让攻击者得逞。
防护措施
禁止将 Session ID 使用 URL (GET) 方式来传递设定加强安全性的 Cookie 属性:HttpOnly (无法被 JavaScript 存取)设定加强安全性的 Cookie 属性:Secure (只在 HTTPS 传递,若网站无 HTTPS 请勿设定)在需要权限的页面请使用者重新输入密码3. Session Fixation (固定 Session ID)
攻击者诱使受害者使用特定的 Session ID 登入网站,而攻击者就能取得受害者的身分。
防护措施
在使用者登入成功后,立即更换 Session ID,防止攻击者操控 Session ID 给予受害者。禁止将 Session ID 使用 URL (GET) 方式来传递那要怎幺防範攻击呢?当然会有人说,会员卡不要掉不就没事了吗?当然我们没办法确保用户不会因为各种方式导致 Cookie 遭窃(XSS、恶意程式等),因此最后一道防线就是网站的 Session 保护。一张会员卡上如果没有任何可识别的个人资料,当然任何人捡去了都可以用。如果上面有照片跟签名呢?偷走会员卡的人在进入俱乐部的时候,在门口就会因为照片跟本人不符而被挡下来。Session 保护也是一样,怎幺让我们的 Session 保护机制也能辨识身分呢?答案是利用每个使用者特有的识别资讯。
每个使用者在登入网站的时候,我们可以用每个人特有的识别资讯来确认身分:
如果在同一个 Session 中,使用者的 IP 或者 User-Agent 改变了,最安全的作法就是把这个 Session 清除,请使用者重新登入。虽然使用者可能因为 IP 更换、Proxy 等因素导致被强制登出,但为了安全性,便利性必须要与之取捨。以 PHP 为例,我们可以这样撰写:
除了检查个人识别资讯来确认是否盗用之外,也可以增加前述的 Session ID 的防护方式:
Session 的清除机制也非常重要。当伺服器侦测到可疑的使用者 Session 行为时,例如攻击者恶意尝试伪造 Session ID、使用者 Session 可能遭窃、或者逾时等情况,都应该立刻清除该 Session ID 以免被攻击者利用。
Session 清除机制时机:
使用者帐号遭窃一直以来都是显着的问题,但却鲜少有网站针对 Session 的机制进行保护。攻击者可以轻鬆使用 firesheep 之类的工具窃取帐号。国外已经有不少网站侦测到 Session 可能遭窃时将帐号强制登出,但国内目前还鲜少网站实作此防御,设备商的 Web 管理介面更少针对 Session 进行保护。如果 VPN Server 等设备有侦测 Session ID 的伪造,在 OpenSSL Heartbleed 事件时就不会有那幺惨重的损失了。
立刻把自己的网站加上 Session 保护机制吧!