本文由作者根据其在KCon 2016黑客大会上的演讲内容整理而成。演讲稿链接:Binder fuzzing based on drozer。
文章开始,先来看几个我在工作生活中发现的Android漏洞。其中包括Android系统锁屏密码绕过(影响了所有安全补丁在2016年10月份以前的Android 6.0、6.0.1、7.0系统)、三星手机关机窃听、三星手机越权修改主题、系统拒绝服务漏洞。然后我们再来解释相关的技术知识和实践。
Android漏洞案例
Android系统锁屏密码绕过
先来看下漏洞视频演示:https://v.qq.com/x/page/u0543o9s9fk.html
这个漏洞当时影响 6.0、6.0.1、7.0的所有最新Android系统。运行exp(exp可以是一个没有申请任何权限的APK,也可以是一个二进制的bin文件),就可以清除Android系统的锁屏密码,这里的密码包括指纹密码、手势密码、pin码和password类的所有密码类型,然后就可以成功重置密码。
该漏洞前后有两个CVE(Common Vulnerabilities and Exposures,国际通用的漏洞编号)编号:CVE-2016-3749和CVE-2016-3908。
我在2016年5月份提交给Google,6月1号收到回复:Google内部安全研究员,在4月13号已经发现了该漏洞,漏洞状态置为duplicate。
继续深入分析发现:使用另一个Android 6.0.1分支版本进行测试,发现另一个函数也存在安全漏洞,这个漏洞函数对应的数字和之前的漏洞相同,Android系统漏洞众多的一个很大原因就是碎片化问题。发现这个问题之后,出于一些考虑,并没有马上提交给Google,等Google发布漏洞patch。
Google于7月份发布了该漏洞公告,CVE编号CVE-2016-3749,而patch代码只是修复了我第一次提交的漏洞位置setLockPassword()和setLockPattern()。
于是在漏洞公告发布当天,我又提交了另一份漏洞报告给Google。
Google于2016年7月20号确认该漏洞为高危漏洞,于8月31号分配了CVE-2016-3908,于10月份发布了漏洞公告并致谢。
三星手机关机窃听
漏洞视频演示:
https://v.qq.com/x/page/o0543t0uwkw.html
漏洞细节:
CVE-2016-9567
漏洞原理:
通过未授权访问setmDNIeScreenCurtain()函数,可以控制手机的屏幕,从而造成关机的假象,实现关机窃听。
三星手机越权修改手机主题
三星居然将其与关机窃听这个漏洞合并了!
漏洞视频演示:
https://v.qq.com/x/page/y0543skh3t7.html
系统拒绝服务漏洞
漏洞视频演示:
https://v.qq.com/x/page/a0543ilaytw.html
这样的漏洞很多,上面视频演示中,通过一个NFC tag来实现漏洞利用。
读者如果想了解具体的实现方式,可以参考作者之前写的文章《Android漏洞利用方式之NFC浅析》。
上面这些好玩的漏洞都与Android Binder有关,接下来我们就带你一起来体验Android Binder相关的漏洞利用技术和工具。
Android Binder简介
"In the Android platform, the binder is used for nearly everything that happens across processes in the core platform."
–Dianne Hackborn,Google
https://lkml.org/lkml/2009/6/25/3
Android Binder是知名女程序员Dianne Hackborn基于自己开发的OpenBinder重新实现的Android IPC机制,是Android里最核心的机制。不同于Linux下的管道、共享内存、消息队列、socket等,它是一套传输效率高、可操作性好、安全性高的Client-Server通信机制。Android Binder通过/dev/binder驱动实现底层的进程间通信,通过共享内存实现高性能,它的安全通过Binder Token来保证。
Binder里用到了代理模式(Proxy Pattern)、中介者模式(Mediator Pattern)、桥接模式(Bridge Pattern)。熟悉这些设计模式有助于更好的理解Binder机制。需要了解以下概念:Binder、Binder Object、Binder Protocol、IBinder interface、Binder Token、AIDL(Android interface definition language)、ServiceManager等。下图大致描述了Binder从kernel层、中间件层到应用层中涉及的重要函数,本文漏洞利用部分会用到。
读者如果想深入了解Binder,推荐阅读:
Android Binder Android Interprocess Communication。
drozer的架构和高级用法
drozer是MWR实验室开发的一套针对Android安全审计和攻击利用的框架,类似于Metasploit。drozer由三部分组成:Console、Agent、Server。下面第一张图为Agent界面,运行在手机端,下面第二张图为Console界面,运行在PC端。
Agent是一个只申请了internet权限的非特权App,它会开启一个ServerSocket服务,默认监听31415端口。Console连上Server之后就可以控制Agent与Dalvik虚拟机、第三方App的IPC节点(intent)以及底层操作系统进行交互。为什么一个无特权的Agent应用可以无缝与Dalvik虚拟机进行交互呢?
drozer使用了反射和动态类加载的技术。下图右边的部分是官方提供的drozer模块的demo,可以看到这么一行,直接可以new一个Java类对象实例,这里内部实现就用到了Java反射机制。左边的部分是drozer源码的一个目录,可以看到有许多.java源文件和对应的APK文件,drozer使用了动态类加载机制,在运行相应模块时,会将这个APK文件上传到手机上Agent应用的缓存目录,使用动态类加载机制调用类里的Java函数。这个功能很实用,在本文第三部分还会涉及到这部分知识。
关键代码:
drozer有两种模式:直连模式和基础设施模式。Android应用安全审计用到最多的就是直连模式,手机端装上Agent应用,通过USB连接电脑,Console端通过端口转发后即可发送命令给Agent端的Embedded Server,来实现对Agent端的控制。
基础设施模式多用在远程攻击利用上:如下图你可以手动设置Server的host和port,以及是否需要开启密码保护和SSL。
也可以通过源码编译一个无launcher的恶意Agent,只需要下图中一条命令。
编译时可以指定Agent回连的server IP 、port,并且可以通过设置密码来做身份鉴权,只有通过认证的用户才可以与该Agent建立session,因此很适合做Android远控。可以在一台服务器上开启drozer Server,如下图所示命令。
当用户中招(可以通过社工、钓鱼等手段诱导用户下载安装),Agent连上来之后,你可在以任意一台电脑上通过Console连上Server来控制Agent。你可以远程下载安装相应的攻击插件,比如打电话、发短信、读取联系人、上传下载Sdcard文件等。开源的drozer-modules比较好用的有curesec、metall0id。这些功能在Android 4.3以下很好用,在高系统版本由于各种安全机制的限制,导致许多攻击功能无法完成。
下图展示了用户中招后,通过远程下载安装drozer利用模块,实现读取用户联系人、打电话、中止来电的功能:
drozer是模块化的,可扩展。上文也提到了许多开源的drozer攻击模块。那么如何写一个自己的插件呢?
有两个要素:
1.图中显示的这些元数据是必须的,哪怕是空。 2.execute()函数是核心,在这里执行自己的逻辑。
基于drozer的自动化漏洞挖掘技术
fuzzing是安全人员用来自动化挖掘漏洞的一种技术,通过编写fuzzer工具向目标程序提供某种形式的输入并观察其响应来发现问题,这种输入可以是完全随机的或精心构造的,使用边界值附近的值对目标进行测试。为什么选择drozer来做fuzzing框架呢?可扩展、易用是最大的原因。下面简单介绍我如何使用drozer对Android Binder进行fuzzing测试。
介绍两种:fuzzing intent、fuzzing系统服务调用。
第一种fuzzing intent。这里我介绍一种通用的方式,不依赖数据类型。这里用到了15年初作者发现的通用型拒绝服务漏洞,可以参考发布在360博客上的技术文章Android通用型拒绝服务漏洞分析报告。简单介绍下这个漏洞的原理:通过向应用导出组件传递一个序列化对象,而这个序列化对象在应用上下文中是不存在的,如果应用没有做异常处理将会导致应用拒绝服务crash。而对Android系统中的一些高权限组件实施这样的攻击,将会导致Android系统拒绝服务重启。 这个漏洞很暴力,可以让很多第三方手机厂商的系统拒绝服务,当然也包括Google原生系统。
第二种是fuzzing系统服务调用。我尽量用大家容易理解的方式来简单介绍这块。Android中有很多系统服务,可以通过adb shell service list这条shell命令列出来。如下图,我的Nexus 5X 7.12系统可以列出126个这样的系统服务。[ ]里是该服务对应的类接口。
这些接口里定义了系统服务用到的函数,下图列出的是lock_settings服务对应的接口类。接口里的每一个函数对应一个整型int值,我们可以对这些函数进行fuzzing,fuzzing其参数。
如下图,我们可以基于shell命令进行fuzzing。举例:adb shell service call lock_settings CODE i32 -1 ,其中CODE部分对应接口类中每一个函数对应的数字,i32是第一个参数的类型,代表32位的整型。
前面提到drozer利用动态加载技术可以加载一个apk文件执行,我们可以利用Java反射机制来确定系统服务中函数的参数个数和类型,然后传入相应类型的随机或畸形数据,这些数据可以通过Ramada生成。
上文也讲到了如何写一个drozer模块,我们只要在execute()函数中执行fuzzing逻辑即可。这里提一下,因为drozer的模块每次修改都需要重新通过module install MODULE_NAME命令进行安装,这里可以把核心功能写在drozer的Python模块里或者写在Java文件里,然后通过外部的Python脚本来自动化这个过程,控制fuzzing的逻辑,通过输出每个fuzzing数据的参数值以及logcat来定位引发漏洞的参数。要注意的是:不是只有Crash才是漏洞,有的漏洞就是正常的调用,并没有Crash异常。我接下来分享的lock_settings服务漏洞就属于这种类型。至此,你就可以写个自己的fuzzer进行自动化漏洞挖掘了。
最后,我们再介绍几种漏洞利用方法。
漏洞利用方法分享
结合AIDL利用
在Android开发中,可以使用Android SDK tools基于AIDL文件自动生成Java语言的接口文件。读者可自行了解更多关于AIDL相关知识。可以参考:对安卓Bound Services的攻击。
关键代码:
通过Java反射利用
和第一种利用方式类似,只是不需要根据AIDL文件生成Java接口文件,直接通过反射利用。
关键代码:
结合Android源码利用
需要将利用代码放在Android系统源码目录进行编译。参考BinderDemo。
关键代码:
通过Java调用shell脚本利用
关键代码:
代码语言:javascript复制Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec(command);
shell脚本内容举例:
代码语言:javascript复制service call lock_settings 10 i32 0