Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

Understanding and Defending the Binder Attack Surface in Android

论文下载

密歇根大学 Huan Feng and Kang G. Shin

  • 最近几年诸多CVE都是与binder相关,但都是以之为入口点,没有真正讨论过binder的安全。
  • 作者发现这种攻击的本质在于攻击者可以直接通过操控binder接口来给系统服务注入错误,而系统并没有对数据来源做到很好的鲁棒性。
  • 为了解答这个问题,作者调查了98个google的服务,以及72个三星的服务,以及137个造成崩溃的漏洞。发现数据的校验仅仅在binder的客户端的API上做了,在binder的服务端并没有。例如没有通过public API暴露的RPC参数,以及后续针对这些参数的(反)序列化都没有保护。证明binder的信任边界出错了,这主要由于Android提供了AIDL能够帮助开发者自动生成接口。
  • 作者开发了bindercracker,用来fuzz binder的漏洞,并能够7倍于单纯的黑盒测试效果。并提供了系统及的诊断工具用来binder攻击。

Fig

  • 攻击模型为 APP开发者可以任意构造binder客户端,来调用系统服务端的binder。

Fig

人工审查了binder的漏洞,结果为

Fig

  • 漏洞大多由于由于数据检查发生在调用Public API上,而对于直接对binder发送的数据没有做校验。
  • 包括攻击者可以
    1. 直接给没有通过public API暴露给开发者的RPC方法传参,
    2. 以及有些RPC虽然暴露给public API,但检查也在public API之前,直接调用这些RPC也能导致崩溃
    3. 利用序列化和反序列化过程中校验不严格,直接修改序列化过的数据,导致服务端反序列化的崩溃。

例如IAudioFlinger提供了RPC方法REGISTER_CLIENT,这个方法只会被系统中间层调用,并没有暴露给开发者,所以对于这个RPC的参数,系统服务就不会校验。如果直接通过对binder driver发送一个空参数,就能让这个服务崩溃。系统开发者直接认为RPC接口是外部无法访问的,这个假设是错误的。

这些错误都因为系统开发者认为的信任边界是错误的,他们认为客户端的public API是开发者唯一可以调用的。这种假设也是因为Android提供的AIDL会自动生成代码,帮助开发者完成binder通信,序列化等,事实上,开发者或者攻击者可以完全不需要使用AIDL,而自己手动调用binder和RPC。

Fuzz工具开发

  • 主要问题在于参数的复杂性,以及input可能来自别的binder的output。
  • bindercracker开发了两个组件:
    • 一个记录组件,作为系统中的一部分,收集binder通信的信息
    • 而fuzz组件作为用户层的APP,用来重放和改变记录下来的binder通信内容。

记录组件在binder通信的序列化过程中进行插桩,可以动态的监控到所有的参数类型和结构,并记录下依赖关系。然后fuzz组件通过对最外部的那次通信数据进行修改来fuzz。主要通过修改binder_transaction_data结构体中数据来进行Fuzz。首先需要找到binder的对应系统服务和具体的RPC方法的关系,这个可以通过解析代码和动态的方式找到对应关系。其次是控制一次binder通信中的数据。

Fig

基本思路就是通过记录下来的binder通信数据可以获取数据结构和必要的依赖信息,最后精确的找到真正需要fuzz的参数数据,保持其他的都不变,只改变一个参数值,这样来fuzz。观察binder服务端的反应,如果服务端接受了数据,并且没有catch到异常导致崩溃,则认为fuzz成功。

结果运行了30个APP,抓取到了超过一百万个binder通信数据,通过对每个RPC接口的binder数据采样,最后fuzz了78个系统服务的445个RPC方法,找到了89个漏洞。7倍于同样时间的单纯黑盒测试效果。此外通过简单配置,可以直接对基于binder机制更高一层的Intent做fuzz,并找到了超过20个intent通信的漏洞,主要在反序列化的阶段。

防御

  • 作者认为静态的方法可以类似android目前已有的lint工具,作用在RPC函数上,或者使用bindercracker来做动态的测试都能提高安全性。
  • 接着介绍了bindercracker找到的一系列案例的安全问题,例如可以导致崩溃,或者重启系统,或者一些提权漏洞等等。以及他们的修补情况。

Fig

最后作者尝试了在现有系统中加入动态实时的防御措施,首先尝试对类似的漏洞的入侵检测/防御。这种方法作者认为不可能实现,因为这个需要监控每个binder的参数信息,手机上性能和计算量不行,以及参数变化多端,和用户体验差。接着作者尝试对该漏洞的诊断系统,就是一旦漏洞发生,立马用可视化形式告知用户。由于一个系统服务如果照此crash,系统只会显示服务崩溃,难以找到谁发出这次通信导致的崩溃。作者利用bindercracker的记录功能,做了个可以告警的工具,供用户使用,以弥补现在系统的不足。

Fig