“无事可干”的黑客们早已经把目光从操作系统转移到固件上了,毕竟一旦攻破了固件的大门,那么在其上的操作系统也会门户洞开。现在电脑或者x86服务器系统中固件众多:
UEFI在其中居于中间地位,它的安全性也是重中之重。我们在前文中介绍了UEFI安全启动:
这种技术把UEFI固件当做安全计算基石Trusted Computing Base (TCB),在其上验证操作系统的bootloader真伪,保证我们和操作系统之间不被插入一个伪造的bootloader。
但大家有没有想过,这里有个假设,那就是UEFI固件也就是BIOS是安全而可信的。这年头,谁会那么靠谱呢,如果某黑客拿个Flash烧写器,做个假BIOS怎么办?
要解决这个真假BIOS的问题,就需要我们今天的主角,Boot Guard出场了。今天我们就一起来了解一下它,并顺便看看其他的解决方案。在进入正题之前,我们需要补充一点密码学相关的知识。
密码学基础
很显然,本篇文章的重点在于Boot Guard,而想要更好地理解它的运作机理则需要一定的密码学基础。密码学是一门高深的学科,关于它的论著数不胜数,此处我们只讲大致原理,不讲细节,感兴趣的读者不妨自行寻找完整的资料来深入的理解这门学科。
1.加密Hash(散列)函数
稍有了解的人都知道:散列函数h是使一个较大域的X的值变为较小范围Y的一种数学函数,同时尽可能的使X均匀投影到Y的取值空间中,这样可以减小哈希冲突(你们还记得吗?敲黑板!用数学语言来解释:存在属于X的x1和x2,有相同的对应关系Y,即h(x1) = h(x2),这种情况就叫哈希冲突)的风险,
加密散列函数f是具有如下属性的散列函数:
-
1). 很难找到x1和x2,使得f(x1)=f(x2)(这一性质通常被成为抗碰撞性(collision resistant))。
-
2). 对于已知的y,很难找到一个x使得f(x)=y(这一性质通常被称为抗原像性(pre-image resistance),通俗的讲也就是单向性,即从输出反推输入很难或者耗时很长)。
此外,加密散列函数通常用来在给定x的情况下,快速计算y=f(x)。比较出名的应用有MD5,SHA-1,以及SHA-2系列等等。
加密散列函数在一些需要保护数据完整性的应用中是很有用的,由于其算法的特殊属性,攻击者很难在修改数据(例如某可执行文件)后不被拥有原始Hash值的人发现。同样的,即使攻击者知道原Hash值,他也做不到不改变Hash值的情况下对文件进行替换(pre-image resistance)。
2. 公钥加密法和数字签名
加密,是以某种特殊的算法改变原有的信息数据,使得未授权的用户即使获得了已加密的信息,但因不知道解密的方法,仍然无法了解信息的内容。
人类尝试加密数据的历史悠久,从希波战争到凯撒大帝出处都有它的痕迹,可以单独写一本书,这里按下不表。但在非对称密钥出现之前,一直都是对称密钥,大家都认为,如果想要在双方之间建立机密通信,那么双方就必须约定一个共享的秘密——shared secret,依靠这个共享的密钥进行加密解密。进而如何可靠的传递密钥变得异常重要。
公钥加密法在20世纪70年代末由Whitfield Diffie,Ralph Merkle和Martin Hellman提出。这种方法,一不需要事先约定,二不必事先知道与谁进行安全通信,也正是因为这两点特性,这一技术才会被称为是革命性的,它也是建立在这样一种概念——公钥部分和私钥部分共同组成新形式的密钥——非对称密钥。公钥可以交给任何人,而密钥的私有部分仅被其所有者知道。这就好比是通信双方,有一个人建立了一个保险柜(将保险柜的制造方法理解为私钥),将信息存入其中,并把保险柜的钥匙(公钥)交给另一方,而另一方当然可以拿着这个钥匙获取保险柜中的东西,但他不能,也不必知晓对方究竟是如何制造出了这样一个保险柜。
在受到Hellman,Merkle和Diffie想法的启发后,Ronald Rivest,Adi Shamir和Leon Adelman在几年后发明了RSA密码系统。使用RSA,持有私钥的实体A不仅可以使用该密钥来解密由知道A的公钥的人发送给他的数据,而且A还可以使用他的私钥来对一些数据进行数字签名(给别人配钥匙)。任何持有A的公钥并且可以访问签名数据的人,都可以通过数学手段来验证这一点:数据只能被拥有A的私钥的人来签名——也就是说,只有A可以生成该消息——并且它不会被没有私钥的人修改。
它的数学理论基础在于大质数分解困难,如果大家感兴趣,可以参考吴军的《数学之美》
总的来说大家只要记住,公钥和私钥是一起产生的;公钥谁都可以有,私钥只有自己有;知道公钥、秘文和明文,无法推导出私钥,反之亦然;公钥私钥可以相互验证。
BIOS固件的验证
好了,在了解非对称密码之后,我们来看看如何以及是谁来验证BIOS的完整性。一个显而易见的方法是对BIOS进行签名,用主板生产厂商的私钥进行签名,如果签名校验失败,就拒绝执行BIOS代码,这就是Boot Guard的大致工作原理。但细节往往复杂太多,其中有许多有趣的环节。
Intel Boot Guard引入了一个叫做ACM(Authenticated Code Module) 的黑盒,也把BIOS凭空分成两部分:IBB和OBB。IBB(Initial Boot Block)一般只包括PEI和SEC阶段,OBB(OEM boot block)则是剩余的阶段。
CPU在出厂的时候,ME是处于Manufacture mode,这时主板厂商(OEM)可以通过工具将厂商的主板启动非对称秘钥对中的公钥部分Fuse到pch中的NVRAM中。并
用签名服务器对BIOS image用密钥对中的私钥进行签名。在启动的时候,黑盒ACM先启动,它用Fuse在pch中的公钥验证BIOS是否真的由其对应的私钥签名,如果通过,就跳到Reset Vector执行,否则死机。
这似乎很好理解,但诡异的是ACM也放在Flash上,谁来保证ACM的真伪呢?答案就是ACM是由Intel用ACM私钥签名了的,而由Intel的microcode来验证签名正确与否。
好了,我们可以串起来讲一下了。Microcode验证ACM, ACM验证IBB,IBB验证OBB(想想为什么不用ACM验证整个BIOS,而要分成两步)。OBB后面呢?那就是UEFI安全启动了。整体是这样:
由此一个启动的安全链条建立起来了。它环环相扣,每一步验证后一步,如果其中任何一个呗破坏,则拒绝启动,来保证最终用户看到的界面是安全的。
安全根的问题
如果我们梳理整个链条,源头的源头,在这条河的最上游,信任和安全的原点在哪里呢?
在Microcode,如果你信任它,才能信任最后的结果,也就是它是这一信任链条的根。
那么,我们该不该信任它呢?
实际上Microcode也需要签名,而验证这个签名的就是CPU硬件。在最后的最后,这实际上取决于相信不相信Intel公司。
相信Intel,才能相信Microcode这个黑盒,才能相信它验证过的ACM黑盒,才有接下来的安全链。而CPU硬件是目前是无法伪造的,也目前没有被攻破。
所以现在大部分电脑厂商,包括笔记本和台式机,总的趋势都是接受并开启了Boot Guard,把主板的安全水平提升了一个档次。
但服务器领域和部分国产领域,则交出了不同的答案。大的云服务器厂商如Google和国产大厂,需要把安全根掌握在自己的手上,选择关闭Intel Boot Guard,换上一套自己的安全链条。即把安全根从Microcode转到BMC或者FPGA中去,来自己掌控命运。
后记
最后说一句,广大最终用户别想着自己关闭Boot Guard。一旦开启就不能关闭,这也是为了安全计。
作者:老狼