【原创】 我们经常看到某某网站被拖库,从而导致用户口令或口令的HASH值泄露,从泄露的HASH值来看,口令的一次MD5或一次SHA-1居多,且未加盐。通过简单的在线破解查询,可以获得很多用户的原始口令。可见,在对用户的口令防护上,大多企业并没有采取安全上的最佳实践措施。
那么我们应该如何保护用户的口令不受拖库影响呢?
笔者认为,一项安全措施,按照它在达成安全目标上的作用大小,可以分为主保护措施和辅助保护措施。就像电力或电子学当中的主电路、辅助电路,或者医学中的“君臣佐使”。下面分别来看。
主保护措施
用户侧(Web前端、客户端)的安全措施,从安全意义上讲,是不可以被信任的,因为用户侧的安全措施都是可以被绕过的。那么,对用户口令的主保护措施只能在服务器侧实施。
这个主保护措施主要包括两方面的内容:
(1) 存储加密
服务器侧在数据库层面的存储加密措施,就是 高强度的加盐HASH。
加盐的目的,是为了对抗预先计算(即通常所说的“彩虹表”,经过预先计算并索引后的HASH值)。
MD5和SHA-1,目前已被公认为弱散列算法了,应予以淘汰。
强散列算法,目前主要使用的有SHA-2和SHA-3两大类,其中SHA-2包含SHA-224、SHA-256、SHA-384和SHA-512这四种具体的散列算法。SHA-3更安全,但是在实际使用过程中也许找不到适用的成熟的第三方库函数,在当前阶段,推荐首选SHA-512加盐,既能保证散列强度,也能找到成熟可用的库。
在认证过程中,还有一个非常关键的地方,就是如果前端(用户侧)已经具备加密措施,服务器拿到的已经是若干次加密后的口令,这时服务器都必须再执行一次加盐HASH操作,否则就相当于明文存储了。
(2) 传输加密
为了避免口令在传输过程中被嗅探,需要启用加密传输通道。通常,首选为Web服务器配置数字证书,启用HTTPS加密通道,可以很好的防止被嗅探,这也是笔者推荐的传输加密方式。
可能还有一些业务场景,出于性能的考虑,业务部门一时半会还不愿意配置https证书,当前也可对口令这个字段进行加密(即在明文的HTTP通道,传输加密后的口令),比如在网站前端内置RSA公钥(字符串),服务器侧应用中配置RSA私钥(字符串),使用RSA公钥对口令加密后传输,只有服务器可以解开得到用户口令,这也是前端慢加密的一种实现。但是,这种方式有一个明显的缺陷,口令密文虽然不能被嗅探者解开,但可以直接当口令用,嗅探者可以拿这个密文当做口令进行重放。因此,如果采取这种字段加密传输的方式,服务器侧还必须具备防止重放的能力,比如传输的是 RSA(口令 时间),服务器还原后提取并校验时间误差是否在指定的误差范围内。
辅助保护措施
(1) 服务器侧的辅助防护措施
服务器侧的辅助保护措施,主要体现在防止自动化的撞库或爆破方面。
首先,需要给每一个Form启用CSRF Token(首选在框架层面启动防止CSRF的Token),这样自动化工具在提交之前,需要先抓取Token,提高了自动化工具的攻击难度。
其次,限制同一用户的尝试频度,达到指定的错误次数(3次比较常见),即开启CAPTCHA机制(各种随机码,如图片、音视频、短信、算式、趣味问答等)或锁定机制(即N分钟内不允许再尝试);
为了防止绕过,规则上还需要:
- 在校验口令之前,先校验CAPTCHA随机码;
- 除了防止通常的基于固定用户名来撞弱口令、基于已泄露的(用户名:口令)对,还要防止基于固定弱口令来撞用户名的场景;
- 考虑内网用户登录(IP Cookie UA)等场景。
此外,还可以从Web服务器自身的配置、WAF配置上对通用的猜解尝试进行阻断。
(2) 用户侧的辅助防护措施
用户侧的辅助保护措施,主要体现在增加破解难度,延长破解时间方面,这种技术措施通常被称之为前端慢加密。前端慢加密占用的是用户的计算资源(JavaScript),由于时间很短(通常远小于1秒),对用户体验基本不会造成影响。
慢加密函数可以采取重复执行HASH函数、scrypt函数、RSA加密等来实现。
慢加密结果 = 慢加密HASH函数(口令 前端盐值) or 慢加密结果 = RSA (口令 时间) or 其它组合方式
前端在传输之前,对口令执行比较耗时的加密操作,将慢加密的结果作为口令提交。慢加密措施是自动化工具绕不过去的一道坎,工具在提交之前,也必须基于密码字典执行同样的慢加密动作,在拖延时间方面可以起到很好的作用,直至令攻击者耗不起,从而放弃尝试。如果执行秒级的慢加密,则针对不特定用户的自动化工具就失去了意义。
即使数据库被拖库,按照前面所述,数据库中存储的是:
SHA512 ( 32位以上慢加密HASH结果 后端盐值 )
其中,32位以上慢加密HASH结果本身就是超高强度的口令,彩虹表几乎不可能对这样的数据进行运算,加盐就更让彩虹表成为不可能,而只能爆破。
要想破解,只能从前端开始,从密码字典提取口令,从网页提取前端盐值,执行慢加密,再执行SHA512(慢加密结果 后端盐值)来跟数据库中的数据进行比对,这个效率显然非常低。如果HASH慢加密不加盐,则有可能先把全部弱密码执行一次慢加密缓存起来,这就达不到拖延撞库者的效果。如果是RSA,黑客还必须拿到服务器侧的私钥才有可能启动破解。
前端盐值会直接暴漏在黑客面前,而后端盐值在没有被拖库的时候还是保密的。前端盐值与后端盐值,应使用不同的盐值,以降低风险。
保护口令的最高境界
如果采取了本文所推荐的安全措施,就算黑客拿到了数据库,用户的原始口令也拿不到,这是因为:
保护口令的最高境界是:
- 就算数据库被拖库或者被内部泄露,也没什么用处,让黑客不可能从泄露的数据中获得用户的原始口令等任何有用的信息。
此外,打铁还需自身硬,安全的设计与开发、安全测试、安全部署、安全验收等SDL关键环节均执行到位,不将漏洞带入生产环境,让黑客无计可施,另寻其它目标去吧!
(完)