本次分享介绍了安全问题的成因可分为设计不当、实现不当、使用不当三类。设计类安全问题的数量相对较少,但形式变化无穷,而且一旦出现往往影响深远,解决成本巨大。同时,如果能在设计阶段就能引入安全考量,不但能减少设计出来的安全问题,也可以缓解其它类安全问题带来的风险。
大家好!刚才听了李海波博士关于语音信息处理的回顾和展望的精彩演讲,我就在想:虽然说今天我们看人工智能没有达到科幻小说期望的那样,有的时候还是“人工智障”的状态,不能像《2001:太空奥德赛》中的HAL那样能够真正成为站在我们身边的伙伴,但在某些场景中,已经能够做一些事情了,例如下围棋、语音识别,等等;不过我相信,在真正匹敌人类智慧的所谓强人工智能出现之前,很多工作还是只有人类才能完成。
另外,第一次工业革命、第二次工业革命并没有消灭人类的工作,计算机出来的第三次工业革命之后,也没有消灭人类的工作。没有计算机就不会有程序员这种职业、也没有腾讯,今天在座各位的工作都是计算机技术带来的。我相信人工智能的发展,一定会让人类世界有一些变化,但也会创造出一些新的岗位。
在信息安全领域,很重要的一类工作是发现安全问题。最近这些年,自动化技术,包括一些人工智能技术在这个领域的引入,帮助我们发现了越来越多的安全问题。以前很繁复的工作,现在可以用一些相关技术帮我们减轻很大工作量。不过今天要分享的不是这方面的内容,今天要讲的内容是目前阶段暂时还难以用AI技术处理,并且在未来很长时间内也一直需要由人去做的部分。如果有一天这部分内容也可以通过AI来做,那就说明匹敌人类的强人工智能已经出现了。
今天我讲的题目叫“代码未写,漏洞已出”。在一般的认知当中,安全漏洞是写代码的时候写出来的。但实际上在所有安全漏洞中,有一类问题不是这样,这就是设计类的问题。它数量可能没有实现上的问题那么多,但这类问题一旦出现,影响深远而且巨大。最重要的是修复可能非常困难。房子哪块砖用的质量不好可以换掉,但是最初房子的建筑图纸画错,这个问题就不是换几块砖能解决的。
这张照片大家看出什么问题了吗?是一个密码锁,大家一看就能猜出这个密码很可能是“3456”对吧。如果没有真正把这个锁投入使用,一把新锁拿到你面前问设计有什么问题,你可能也想不到这个地方不该用油漆。坏的设计就像这样,本身会形成安全问题。而好的设计不仅仅可以做到自身安全,同时即使在实现阶段或其他的环节有人犯错误的时候,好设计可以降低这些问题的危害。做到这两点,就是一个在安全角度上看真正的好设计。现实中,真正好的设计是不容易做出来的。
我们说这类安全问题属于设计不当,而设计不当又分两种。一种是单点设计不当,就是在设计当中某一个局部有一个小问题。还有一些问题是耦合性问题,多个点的耦合问题。多点耦合是相对的,因为单点问题往往也需要和其他点配合来最终形成危害,只是从大的方面看,更多问题出在内部。多点耦合问题又分系统内的耦合问题,以及设计的系统和其他系统间的耦合问题。除了系统和系统之间的耦合,还有一个常常被忽视的是系统和人的耦合。因为人其实也是系统,你的用户也是一个系统。
下面举几个比较有代表性的例子。首先我要强调的是,安全意识有时代背景。下面谈的这些问题,不全是设计者的错误。有些设计过去可能不被认为是安全问题。但时过境迁,一些新的安全攻击思路出之后,这种设计就不安全了。不能以今天的标准去苛求过去。比如岳飞,他是民族英雄,但当年也镇压过农民起义。今天我们提到岳飞还是说民族英雄,而不说军阀。
这是Java 6.0消息摘要类中的一个函数,用来验证HMAC等数据。在这个函数本身设计的时候,这种写法可能还不被认为有太多问题,在座各位看这个函数可能也觉得没什么问题。但如果我们用刚才的这个函数去验证一个重要数据,假设digesta是我们掌握的密钥,用户传递的密钥是digestb,实际上用户可以用逐字节穷举的方式很快探测出真正的密钥。我们看这个函数是怎么验证比较的呢?它是一个字节一个字节比较的。第一个字节不正确,它立即就会返回失败。如果第一个字节是对的,就比较第二个字节。所以,如果用户传递过来的密钥第一个字节是对的,和第一个字节是不对的,这个函数返回的时间会有一个微小的差异,整个指令执行周期会多一点。在这种情况下,攻击者本来要把所有数据都猜对才可以破解出这个密钥,而这是几乎不可能的。但是现在他可以一个字节一个字节猜,一下子把猜解速度提高无数倍。
所以在看安全问题的时候,时间这个维度很重要。我们看安全问题,常常更多看数据上的东西,时间维度往往容易被忽视。在计算机中处理的数据,除了关注类型、长度、内容,还要考虑时间因子。什么时候时间开始,什么时候时间结束,持续多久,这些往往会影响安全。和时间有关的安全问题非常多,这里只是举其中一个例子。
安全的设计是什么样子?这是改进后的写法。无论传递进来的密钥是什么样子的,是有几个字节对,是有几个字节不对,它处理的时间是完全一致,攻击者没有办法对通过时间差攻击来进行密钥猜解。
FTP协议大家非常熟悉,但用今天的眼光来看其实是不安全的。就像之前说的,我们不苛求古人,所以不说它是坏的设计,但我们说这是过时的设计。现代意义上的第一个版本FTP是1980年出来的,实际上还有更早的版本。FTP现在是用两种模式,一种是最原始的主动模式,1994年又出了被动模式。但这两种模式以今天的安全眼光来看都是有问题的。最早的主动模式会导致一种叫Bounce的攻击。被动模式能解决一些问题,但是又会影响服务器的防火墙安全策略。所以FTP的设计在今天来看,虽然做了各种调整,但是还会有各种各样的问题。
主动模式FTP的协议是这样工作的。首先我们连接到172这台机器,假设它是FTP服务器——今天是创新日,大家看这也是一个微创新,这页PPT里的击键仿真动画不是嵌入的视频,是用PPT自带的功能来实现的——登录进去,服务器返回说OK,你登录进来了。192这个机器假设是内网的一台机器,我们没有办法直接访问它,可能它是一台重要的,受保护的机器。但是这种FTP的协议本身允许用户设定自己的IP。你去访问一个FTP服务器,它当然可以知道你客户端IP是什么,但服务器允许你指定另一个IP作为你的IP。当然,这种设计有其合理原因,在这里不过度展开,大家只要知道它允许这样做就可以。红色的字都是攻击者的命令。成功了。这意味着FTP服务器在这条命令之下连接了192这台机器的1027端口,并且把执行结果发到了内网那台机器上。
如果我们再给它指定另一个端口。这里用1028端口。但是1028端口是关闭的,我们相应的可以看服务器给我们反馈连接失败。在这个过程当中,我们实现了通过这台FTP服务器,间接连接到了一台我们根本没有办法触碰的内网机器,而且探测出那台机器的某个端口是开放或者关闭的,实现了端口扫描。实际上不止扫描,用这个技术还可以发起攻击。它影响了自己的安全吗?没有,但是它会影响身边其他服务器的安全性。这是一个很典型涉及协议的耦合问题,
谈到耦合问题,我就想到了这张图。这是一台交换机,红框处是一个键。这就不能说是历史原因了,因为设计交换机的时候一定已经有网线插头了。而且这种网线插头的设计本身又是很常见的设计,在做交换机的时候,把这个按钮放在这里。如果是稍微粗心一点的人来这么一下,整个交换机就重启了。
我们再来讲一下软件系统之间的耦合。有一个非常经典的例子,国内中小电商,一半以上在早年都犯过这个错误,现在基本都修复了。电商的交易和支付系统之间流程是这样,一个人过来说老板我要买一台冰箱,多少钱?两千。OK,你把钱付给支付系统。因为支付请求也是在用户侧的浏览器里提交的。这个过程对用户是不可见的,但攻击者实际上可以修改这个数据。攻击者可以修改浏览器提交的数据,本来交易系统让他提交2000元,攻击者改为提交1元,然后支付系统就返回OK,说我收到钱了。这个OK到交易系统那里,交易系统一看支付成功了,那就安排发货,1元钱就把冰箱买到了。
大家不要笑,50%以上的电商出过这种问题。支付系统和交易系统在设计的时候,两边看自己的设计都没有问题,但是当你考虑到这个系统接口是要和别人配合的。支付系统要怎么样可以解决这个问题?不要只反馈是否OK,同时也把支付的金额和OK一起返回过去。是支付2000元OK还是1元OK。这就解决了问题,现在的电商都改成这个设计了。
还有硬件耦合的问题。我去年在Tencent Talk上讲过这个例子。这是我们2015年发现的问题,起名叫BadBarcode。条码阅读器这种设备大家非常熟悉,有各种各样的形式。去过机场,大家都会知道机场使用的都是这款机器。
条码阅读器是三大部分,获取图像、解码转换和数据传输。数据传输这里有个和上位机耦合的问题。条码阅读器为了兼容性和用户体验,大多数条都支持键盘模拟模式,把自己模拟成键盘设备。这样条码阅读器插上去根本不需要驱动,把要读取的字符以键盘击键的方式发给上位机。这对软件来说也不需要专门去做读取数据的模块。但这种设计是容易出问题的。
大家看一下我们的例子,我们构造了一个非常特殊的条码,扫过这个条码之后,就可以在它的上位机植入一个程序,并且执行起来。这是一个非常严重的安全问题。不同的条码设备有不同的工作原理,这种内部有一个摄像头去拍画面。还有一些条码设备阅读原理是发射激光,利用反射回来的激光信号去读去数据。大家注意桌面上的光点不是它发射的,而是我们从远处发射的。这个激光可以欺骗设备让它认为自己在阅读条码。你可以从很远的地方发射激光,就可以控制这台电脑做任何事情,只要激光够强从月球上都可以。
这就是硬件之间的耦合问题。设计类问题一旦发生,影响非常深远,而且解决起来成本非常高。过去20年,全世界所有条码阅读器厂家大部分产品都有这个问题,因为整个行业都是这么设计的。过去20年里的设备都要更新?成本太高了。所以厂商没有意愿去解决这个问题。不过我们实验室目前和微信支付合作,对供应商的设备进行检测,和给出修复方案。所以现在微信支付提供给合作商户的条码设备,是没有这类问题的。
我刚才讲了软件设计问题、协议设计问题。下面讲的问题既涉及系统设计,同时又涉及协议设计,而且是多个协议设计,是一个多点综合性的耦合问题。这是我去年发现的,我起了一个名字叫BadTunnel。我这里列了9点,是既往的协议和系统设计,它们诞生的时间点不一样,是由不同的公司不同的人在不同的时间去设计出来的。每个设计独立去看可能没有太大的问题,甚至是很有必要的。但是这九个设计综合在一起的时候引发了一个非常严重的安全问题,从Win95影响到Win10。当时外媒报道它时甚至说是“有史以来最严重的视窗问题”。这九点协议协同工作的过程很复杂,大家可以看一下这个动画。在这个协同过程当中,存在一个非常小的缝隙,它不是一条直的路线,是非常弯曲的路。但是你只要找到它顺着走下来,最终可以实现劫持被攻击者的通信流量,窃取数据,甚至植入病毒。
再下面,我讲两个系统和人耦合的例子。一个是“短信保管箱”,一个是“自助换卡”,这是两个运营商的业务,也算是他们的“微创新”,但是这个微创新是有问题的。
前几年有运营商搞了“短信保管箱”。短信在我们的印象中,是只有手机会收到,除了在手机上看到,在其他地方看不到。所以在很多高安全要求的系统在设计的时候,是把短信作为一个相对可信的因素。比如网银,包括腾讯业务也会向用户发验证短信,通过验证码或者验证链接来确认你的身份。
短信之所以有这个特点,是因为我们假设短信是独立于电脑的因子,也比你的个人电脑可信。但短信保管箱业务是什么?它在运营商服务器上把你的短信存了一份,你在电脑上可以登录网站看短信。本来我们认为短信是独立于电脑的安全因子,用它去验证一些更高安全级别的操作,现在运营商用这个业务之后,你的电脑一旦被别人控制,短信的第二把锁的意义就没有了。电脑一旦被别人控制,你能看短信,攻击者也可以。所以这个东西被很多网络犯罪者使用。所以最终这个业务的宿命就是被取消了。
还有“自助换卡”,这也算是一个微创新。大家看这是公安部的一个微博帐号发的信息,自助换卡的问题这条微博已经讲得很清楚了。这个业务上线之后,很快被网络犯罪分子找到了它的可利用之处。因为这个业务的设计其实是有问题的。这个业务要求你发的信息,一般用户看到没有办法很直观地知道这是要做什么。所以很容易被犯罪分子诱导去发这样一条短信。一旦发了这条短信,你的手机号就转移到犯罪分子那里去了。你的短信、来电,全都到他那里去了。以后依赖于短信验证的安全措施全等于零。因为你的手机号已经给别人了。这个业务的宿命也是下线,如果设计的时候多考虑一些,设计好一点,其实也许可以避免这个问题。所以我们在设计东西的时候,要考虑到内部的耦合,考虑和其他系统的耦合,还要考虑和小白用户的耦合。你要知道使用你系统的人是各种各样的人,和人的耦合过程当中也会产生问题,所以必须要把小白用户的情况考虑到。
所以我们说在做设计和架构的时候,在安全上需要多想一想。一是向外想一想,二是往前想一想。我们知道所有的设计一定会过时,但是我们是否可以做到三年之后、五年之后不要过时?古人说好医生“不治已病治未病”,好的君主“不治已乱治未乱”。好的设计者也应该要把安全隐患扼杀在摇篮当中。