一个有趣的小 Bug 避免了一场大灾难
| 2016-01-22 10:42
我要讲述的这个故事是,在一个下午,视频游戏中的小bug造成的故障,如何促使我去清除来自于软件的潜在危险漏洞,而该软件被来自于世界各地的企业和政府使用。这件事还让我明白了一个实践教训,即你为什么要将代码中发现的问题报告上去,即使一开始它们看上去那么微不足道。
这一切都始于这个秋天一个下午,我正在哈佛商学院上关于创业的本科课程。我们正在学习如何用小组的形式来有效地工作,途径是通过参与一个商学院的模拟游戏,这个模拟游戏是用来教授团队协作专业管理课程的。
我们被分为五组,并被告知我们的目标是共同努力作为一个团队登顶一座山峰。此外,还给了我们每个人到模拟网站的链接,一旦我们登录网站,里面就会有一个屏幕告诉我们,我们在这个团队中需要扮演的独特角色。一个是领导者,一个是经验丰富的登山者,一个是医护人员,而我则是极其有用的环境保护者,嘿嘿
从根本上而言,模拟是一个老式的、回合制的菜单游戏,用Javascript和HTML在浏览器中实现。就像是《龙与地下城》的高级训练版本,在每个回合中,每个玩家都需要对往山上的哪里走,以及如何使用他们的设备做出选择。完成共同的团队目标和特定个人目标还可以获得积分(我的目标自然就是通过清理山上的垃圾来保护自然了,哈哈)。
整个游戏是通过网站上的一系列表格运行的,但除此之外,还有一个一直保持在页面顶部的对话框,它允许你直接发送即时消息给其他玩家,或整个团队。当我的队友对虚拟用品产生争执时,我开始摆弄对话框,并很快意识到,它会换码任何我输入的HTML。
这意味着,我可以通过跨站点脚本,对任意我的队友的模拟页面运行我想要的Javascript代码(如果你不知道跨站点脚本以及为什么换码HTML的重要性,那么我极力推荐这个视频)。
因为有了这个新的权力,于是我发送代码给我的队友们——在他们的屏幕上弹出消息,通知他们如果清理山上的垃圾,就会有奖励积分,以及扮演医护人员角色的人(特别好斗)并不需要登上山顶。我们很快就收集好了虚拟垃圾,同时也放弃了医护人员。我置身于模拟游戏之外,转而让我的队友们互相竞逐积分,并陶醉在随之而来的混乱中。
利用模拟网站中的bug,我制造了很多混乱(当然所有的混乱又都是有趣的),但这绝非严重问题。因为问题内置于游戏,所以即便是最坏的情况,心思不正的学生也只能用来干扰同学,而不能用它来窃取重要信息,也不能像其他著名的跨站脚本漏洞一样劫持帐户。我琢磨着,可能是创造这个游戏的商学院教授,后期将这个网站等的所有事宜都扔给了一个学生去做,而这个学生则匆匆忙忙地在一个喝着咖啡熬夜的夜晚,因为疏忽而遗漏了这个bug。
我本来可以就此放手,随它去,但我一想到,如果有这样一个漏洞在我写的代码中,我会希望别人能够告诉我。所以,我决定负责到底,在课后报告bug。
这就是事情变得有趣的地方了。
我写了一封电子邮件给哈佛商学院出版社,因为它拥有游戏的出版权。我告诉他们,我在这个软件中找到了一个跨站点脚本问题,然后他们要求我能够与他们负责维护模拟优秀的人接触,这样以便于我告知他们漏洞的细节。他们告诉我,此模拟实际上是由第三方软件开发公司创建的,他们会把我提供的消息告知这个第三方软件开发公司,以便于该开发公司可以直接跟进。
好吧,事情跟我想得不大一样。bug不是由粗心学生引进的,它的始作俑者是一家专业公司里的专业开发人员。
现在,你可能会想,这有什么大不了的呢?这只是一个游戏而已。就算有里面有bug,也不会导致什么不好的事情。问题不在于游戏有bug,问题在于,当一个专业的软件公司犯了这样的错误时,往往不会是一次性的。很有可能这家公司所使用的质量保证流程,根本不能捕捉这个这个bug,于是乎,他们甚至有可能正在将这段缺陷代码用于其他客户的项目中,从而导致更多的安全漏洞。
我等了两个星期,也没有收到那家公司任何有关的后续邮件,因此我给哈佛商学院出版社发了另一条消息,想要知道这家公司的名字以及负责人的联系方式。然后出版社告知了我这家公司的名称以及公司CTO的邮件地址。
幸运的是,当我告知CTO bug的时候,他非常敏锐地认识到了问题的严重性,快速跑去验证并解决问题。他证实了公司通过使用由一系列通用工具和模块组成的平台来创建软件,这意味着他们会天然地复制组件,例如不同产品中的即时通讯系统,但他向我保证,所有的bug实例都会被修复。
由于这家公司通过重用模块来创建软件,因此在其产品中的任何一个问题都很有可能存在于其他很多产品中,作为缺陷代码被重用。此外,事实证明该公司使用该平台并不只是为学校教育构建了模拟软件。他们还开发了为“世界各地的企业和政府机构”提供共享和可视化数据的软件,并期望通过浏览他们网站的“案例”部分,许多他们面向业务的应用程序趋向于囊括用户之间的消息功能。这意味着,我们课堂软件中的那个低风险bug,可能会成为实时应用程序处理政府或企业的敏感数据时的高风险bug,导致消息系统易受攻击。
每一个程序员都会犯错,而且像这样的跨站点脚本问题是不可避免的。质量保证流程可能会错过类似于这样的bug,原因或许是因为团队正火烧眉毛地冲刺最后的截止时间,所以规避质量保证能为他们争取时间,而且他们的代码将在系统的低风险部分使用。但是,如果你正在构建软件模块化它,然而却没有重新测试缺陷组件,就把它用到了其他地方,从而让其他地方也出现安全隐患,就可能会造成实实在在的灾难。
当然,不要误解我的意思,我并不是说重用代码不好,重用代码是一件了不起的事情,它能让我们更快速地构建系统,而且通常正确率更高。这个真实的故事告诉我们,得益于重用代码的巨大好处,因此几乎我们使用的所有软件都不可能存在于真空中,同时一个无聊游戏中的bug实际上可能也会导致严重的系统漏洞,防微杜渐,刻不容缓。