在刚刚过去的上星期,2024年的MobiSys会议在日本召开,今天我们就要给大家介绍一篇来自该会议的论文_Automated Detection of Cryptographic Inconsistencies in Android’s Keymaster Implementations_:
先介绍一下本文研究的主角——Android平台的Keymaster(权且管它叫做“加密师傅”?看过《黑客帝国》的读者,还记得里面那个开锁师傅吗?),如果你在Android平台上有过开发(特别是安全开发)的经验,应该对Keymaster不陌生,它就是Android系统提供密码学功能(加密、签名等)的关键组件。可想而知,这个组件对安全的要求应该是极高的,因此,现代Android设备基本上都用TEE来对Keymaster进行保护,而且有些设备为了更高的安全性(并不信任TrustZone~),干脆弄了一个独立的安全芯片(eSE),然后Google搞了个Android Ready SE Alliance技术联盟,管这个芯片叫做StrongBox(靠名字来吓唬人,可惜缩写有点弱),让Keymaster在里面运行。
本文的目标就是去研究Keymaster(在TrustZone和StrongBox)里面的安全性,很可惜,由于MobiSys并不是个专门的安全会议,在MobiSys上发表的安全研究工作,彷佛有点奥运会里面的足球比赛一样,和专业的安全会议(世界杯?)比起来还差点意思。这篇论文的主要工作,用一句话来介绍就是“把万物皆可fuzz的思想用到了Keymaster测试上,然后找到了一堆实现错误。”所以可能稍微没有那么有吸引力,毕竟我们大家都想看的是高难度的漏洞利用对不对?那不管怎么样,我们还是要继续看看本文的研究结果,至于它的技术部分,就简单说一下,不展开细节了。
作者基于此前的Peach fuzzer(https://peachtech.gitlab.io/peach-fuzzer-community 可了解更多细节),开发了一个专门针对Keymaster的fuzzer——AKF,在论文里面这个AKF的设计架构图看起来就非常的平凡。其主要的特色是有一个fuzzing manager(感觉到了浓浓的大企业文化,要配一个manager),负责为Peach fuzzer生成的输入去填上一些能够符合密码算法和协议操作的内容,如下图所示:
设计和实现部分跳过之后,我们可以看看作者对现实世界的Android设备(下表)进行测试的情况。
读到实验部分,我们会发现,这篇论文的发现稍微有点弱,主要是发现了什么问题呢?大部分是Keymaster在各家设备上的实现不一致的问题。怎么去解释这个“不一致”,举个例子,一个特定的Keymaster实现,如果它不支持某种算法组合(例如MD5-RSA)但是又允许用户去提供这种参数,那就是这个Keymaster实现自身的不一致。而如果不同的Keymaster之间没法达成统一,比如三星的Keymaster可以按照特定的参数去生成一个特定的签名,而没法在小米的设备上验签,那就发现了一个Keymaster跨设备不一致的情况。
实际上整个论文最吸引人的部分就是下面这张表,以及对应的论文中的第六章(Findings)。我们可以解释一下下面这个表里面的各项数字的缺陷:
能生成签名但是不能验签:对应NONEwithRSA
这个签名参数,Pixel和三星设备能够生成签名,但是并不能对这种生成出来的签名进行验签;而对SHA1withRSAPSS
参数,作者测试过的Pixel设备中居然有一台没问题,经过他们分析发现,只要你是老的固件版本,就没问题,一旦升级了系统固件,反而产生了问题。
解密失败:对于AESGCMNoPadding
模式的密文,Pixel设备如果没升级固件,它的StrongBox Keymaster就没法解密,这个其实是个老问题(CVE-2019-9465,具体还可以看看 https://alexbakker.me/post/mysterious-google-titan-m-bug-cve-2019-9465.html 这个博客文章),升级了就好了。
“病态”实现:Pixel设备允许APP去调用StrongBox Keymaster时传入一些不正确的参数,但是并不会抛出异常(反观三星的Keymaster就会抛出“Invalid Argument”异常),还允许调用者去创建key,直到最后进行密码学操作的时候才出错,这让APP开发者就很困惑(因为Keymaster在不同的设备上都是一样的接口)。
异常处理的不一致:对于抛出异常的场景,不同的Keymaster实现也有很多不一致(iOS设备笑而不语:“说到碎片化哈哈哈”),三星甚至会对不支持的HMAC抛出一个没有任何信息的“-59”异常,简直是草台班子!
“失而复得”的bug:前面说过,Pixel设备在出厂的时候没问题,升级了固件之后反而会产生“能生成签名不能验签”的问题,而这还不是特例,作者发现,这是因为固件升级以后Keymaster移除了一些算法的支持(例如SHA224、MD5),而使用这些算法的签名模式还保留,这导致了本来没问题的模式中“重新获得”了实现bug。
特定算法组合的实现不一致:作者发现RSAECBOAEP/SHA/MGF1padding
这个有点复杂的模式(也并不复杂,你如果开发过这个代码就知道其实还行),这里面的SHA算法到底是SHA-1还是SHA-2会影响实现,如果用SHA-1是没问题的,但是用了SHA-2就会导致所有基于TrustZone的Keymaster实现全部出错,只有Pixel那个StrongBox Keymaster能够正常工作。作者还联系了三星和Google,三星回复说这个是需要提供一些具体的参数(估计原来文档没写对),而Google的态度是“Google did not provide any worthwhile response”。
对错误参数的非预期操作:对于不同的设备上的Keymaster,在提供错误的密码算法参数时,它们的回复信息不完全相同,这导致了APP可能要为了不同的设备去设计不同的逻辑(嘿嘿嘿,这算啥,人家为了不同的Android设备的屏幕尺寸都要进行不同的适配,你这一个小小的不一致还叫苦?)
对不支持算法的非预期操作:和前面一条差不多,不同家设备的Keymaster能支持的算法模式是不一样的,有些设备可能厂商比较良心,就给你都实现了,有些厂商懒一点或者有点洁癖,就把不太安全的算法模式都裁剪掉,这种情况下开发者也会收到不一致的调用回复。
其实,Android碎片化这种问题也不是第一天出现了,都过去了这么多年,你不去适应碎片化,难道还指望碎片化来适应你?当然,我们也希望给大家打打气,你看这个世界其实就是个挺大的草台班子,希望大家还是能相信“认真的人永远存在”,不管是发现问题还是去解决问题都更加细心一点,让世界多一份美好!