慈善黑客行动:自动化漏洞挖掘在LibOTR库的实践
去年年底,我们利用为DARPA网络大挑战赛开发的自动化漏洞挖掘技术探索了新应用方向。当其他参赛者正为CGC决赛做准备时,我们尝试将漏洞挖掘工具应用于真实的Linux应用程序。
这个故事始于一场赌约:2014年11月4日,Thomas Ptacek(Starfighter)与Matthew Green(约翰霍普金斯大学)打赌,认为安全消息软件常用库libotr在12个月内会出现高危漏洞(如远程代码执行、信息泄露)。作为Trail of Bits团队,我们喜欢这样的慈善赌约,而且正好有一套闲置的自动化漏洞挖掘系统。于是我们决定使用网络大挑战赛的系统对libotr进行漏洞挖掘。
需要说明的是,这并非正式的安全审计。我们只是想测试自动化系统在真实Linux软件上的表现,并为慈善事业赢取资金。
我们成功增强了漏洞挖掘系统以支持libotr库并进行了全面测试。系统确认在测试的代码路径中不存在关键漏洞;由于无人报告其他漏洞,最终Matthew Green向Partners in Health捐赠了1000美元。
接下来将详细介绍加密通信系统给自动化测试带来的挑战、我们的解决方案以及测试方法。当然,我们的系统未在libotr中发现漏洞并不代表该库完全没有漏洞。
背景技术
我们为网络大挑战赛构建的自动化漏洞挖掘系统(称为网络推理系统CRS)原本针对DECREE操作系统的二进制代码运行。虽然DECREE基于Linux,但与标准Linux存在显著差异:无信号、无共享内存、无线程、无套接字、无文件,仅支持七个系统调用。这意味着DECREE与libotr等Linux库在二进制和源代码层面都不兼容。
经过权衡,我们决定将libotr移植到DECREE,而不是为CRS添加完整的Linux支持。我们采用通用化移植方法,以便将来测试其他Linux软件。
移植libotr需要解决两个主要问题:共享库依赖(libotr依赖libgpgerror和libgcrypt)和libc支持。我们使用LLVM一次性解决这两个问题:首先用whole-program-llvm将libotr及所有依赖编译为LLVM位码,然后在位码层面合并所有共享库并进行激进优化。这样既消除了共享库需求,又大幅减少了需要实现的libc数量(未使用的libc调用被优化掉)。我们结合挑战二进制文件中的libc实现、剔除DECREE中无意义的存根函数,并基于DECREE调用创建新实现,最终构建出可在DECREE运行的libc。
自动化测试技术
加密通信应用本身难以进行自动化审计:如果自动化系统能推理密文与明文的关系,加密系统就已经被攻破。这些系统也难以通过随机测试(如模糊测试)进行审计,因为接收方会验证每条消息的完整性。
通常测试加密系统时会关闭加密(或在加密前/解密后操作数据)。为模拟黑盒二进制测试,我们未对libotr做任何修改,而是让CRS模拟中间人(MITM)攻击。由于测试的是未修改的libotr,CRS无法有效攻击通过消息完整性检查的代码,但仍可攻击消息控制数据、头部以及解密/认证代码中的潜在缺陷。
问题是CRS原本并非为MITM设计。我们转而架构测试应用程序(非libotr本身)使其更易受攻击,形成了以下复杂架构:
CRS作为中间人介入两个使用libotr通信的应用之间。
创建测试应用比移植libotr到DECREE更困难。移植过程相对直接,耗时约两周。示例应用开发时间更长且更令人沮丧:官方libotr发行版没有示例代码,文档也不完善。
我们的测试受限于示例应用使用的libotr功能(如未使用SMP)以及特殊的测试应用架构。此外,某些漏洞可能仅在解密后出现,而加密认证数据的修改永远不会触发这些漏洞。
测试结果
libotr测试结果令人鼓舞:我们使用48个Xeon CPU对libotr示例应用进行了24小时测试,未发现任何内存安全违规。
CRS作为中间人介入两个使用libotr通信的应用之间。
这一阴性结果不意味着libotr没有漏洞。我们只测试了libotr的子集,仍有大量代码未被审计。但未发现明显漏洞已是非常积极的信号。
结论
libotr赌约期限已过,期间未报告任何高危漏洞。我们使用自动化漏洞挖掘工具审计了部分libotr代码,也未发现内存破坏漏洞。在此过程中,我们学会了将Linux应用移植到DECREE的方法,并验证了CRS能够识别Linux程序中的真实漏洞。更好的文档、测试和覆盖所有libotr功能的示例应用将简化自动和手动审计流程。本次实验我们坚持使用未修改的libotr,未来计划通过修改libotr来简化自动化测试。
分享渠道:Twitter | LinkedIn | GitHub | Mastodon | Hacker News