----无数事故告诉开发人员:将散列机制引入密码很有必要
在经历了众多后果严重的数据泄露事故之后,开发人员是时候重新审视自己的传统思维、意识到将密码直接加以存储有多么危险了。不过别怕,一套极具可行性的替代方案已经前来救场。
上个礼拜,我参加了一次项目讨论会议,打算借此机会为一批软件开发人员提供点安全性建议、从而帮助其为我们打造出更出色的面向客户应用程序。但是在面对他们提出的问题时,我实在有种魂飞天外之感——“我们应该如何对密码进行加密?”同志们,身为开发人员,你们不能这样啊……之所以提出这样的问题,大概是这群开发人员觉得将安全议题纳入讨论会给我留下深刻的印象甚至因此对其产生好感。毕竟他们想到了要对数据库中收集到的密码信息进行加密,这在一定程度也算是种良好的开端。但我得冒昧地提一句,这样的状况没能让我产生丝毫的振奋之情。理由很简单,我所希望听到的问题应该是“你为什么希望把密码内容都汇总在一起?”会议上的交流互动让我回到了十年前,而且令我痛心疾首的是,虽然已经有众多数据泄露事故可以作为前车之鉴、但很明显残酷的现实仍然没能迎来实质性的转变。
而且即使是十年之前,当软件开发人员问及应该如何如何对密码进行加密以实现数据安全保护时,我给出的答案也是一样——“别这么做”。最佳实践早已经过了时间的验证,正确答案是我们压根就不应该把密码或者信用卡号码这类由客户产生的敏感性数据储存起来。没错,我们需要的不是存储、而是验证。
对于密码,其起效机制可以总结如下。用户需要在每一次登录时手动输入自己的用户名以及密码内容。而我们的最佳措施则是获取所输入的密码并进行散列处理(即利用MD5或者SHA等散列算法计算出一个独一无二的值),并将由此获得的散列值与应用程序此前保存在数据库当中的散列值进行比较。如果两个值能够完全匹配,则证明用户输入的密码内容准确无误。这种方式彻底消除了保存密码内容的必要性。具体而言,应用程序只需要将获取用户输入到密码栏内的数据、并对其进行实时散列计算即可——就这么简单。
十年之前,我们使用的是MD5散列算法。时至今日,MD5已经有些过时,所以我们会转而通过SHA-2算法加以替代,但由此带来的结果是完全相同的。就在不久前撰写的另一篇文章中,我将散列称为一种作用于认证系统开发的“尝试与核实技术”。我也同时强调称,当下每一位开发人员都应该采取这样的安全实现方式。
有鉴于此,我对于上述情景感到意外——甚至有些震惊——直到今天,开发人员们还在傻傻地讨论该如何对密码存储进行加密。他们仍然在走一条已经被无数事故狠抽过耳光的安全死路,即对密码内容进行加密、并将其与用户所输入的实际密码数值进行直接比对——而非借助散列计算值。这简直是疯了。无论是什么样的数据库都不可避免地面临着遭受入侵的风险,而保存在其中的密码内容也当然无法幸存,因此直接存储就是最蠢最不可理喻的处理方式——没有之一。
而这种状况还真应了无独有偶、祸不单行的俗谚。从LinkedIn、eBay到Twitter再到其它众多企业,过去几年中遭遇数据泄露事故的厂商可以说不胜枚举,而且一个来自俄罗斯的网络犯罪团伙宣称他们从上述企业手中窃取到了总计12亿条密码。面对这样的状况,今时今日、我们真的还要坚持密码内容直接存储这种玩火自焚般的机制?我想我绝不是惟一一个力荐大家将其摒弃的安全从业人员。
我旋即向开发团队发出了一条建议:不要存储密码内容,而应存储散列值。他们马上明白了我的观点,表示这个主意很好很强大,并打算立刻着手执行。也希望大家能够对此引起足够的重视,因为在软件中最重要的组成部分——登录机制——埋下如此可怕的隐患实在是大大不该。
原文链接:
核子可乐译