专栏首页FreeBufCVE-2016-10277在MOTO X手机上的漏洞利用实践

CVE-2016-10277在MOTO X手机上的漏洞利用实践

CVE-2016-10277是存在于摩托罗拉系列手机的bootloader高危漏洞,可以通过内核命令注入劫持手机的启动流程,加载攻击者控制的initramfs,从而达到root提权的目的。我们手上正好有一个摩托罗拉的MOTO X手机,于是参照[1]的漏洞利用过程,将CVE-2016-10277的漏洞利用过程实践了一把,复现过程还是十分曲折。

0x00 系统环境

1.手机: MOTO X(XT1581) 2.系统固件版本: 3.Android版本:5.1.1

在漏洞利用过程中需要用到手机boot.img中的aboot、initramfs,手机没有root的话是无法提取系统固件的,幸好我们在网上找到了对应的系统固件,可以直接提取使用。

0x01 漏洞原理

CVE-2016-10277的基本原理并不复杂,主要就是可以通过fastboot向bootloader注入内核命令参数。首先我们可以通过fastoot oem config 查看配置参数:

这些参数都未受保护,即使bootloader已锁,仍然可以通过fastboot oem config命令配置:

漏洞就在于bootloader未对配置的这些参数进行过滤,而这些参数会直接传递给内核的命令行。内核命令行参数的注入会影响bootloader的加载过程,攻击者如果精心构造某些参数,将达到控制手机启动,甚至root提权的目的。

0x02 漏洞验证

首先我们要先确定MOTO X是否受CVE-2016-10277漏洞的影响。

1) 注入参数设置property

执行命令:

fastboot oem config fsg-id "a androidboot.bar=1"

该命令注入了androidboot.bar=1参数,该参数如果注入成功,将会设置系统的ro.boot.bar属性为1。当然,这里我们只是虚构了一个bar属性。

2) 启动系统查看property

执行命令:

  fastoot continue
  adb shell getprop ro.boot.bar

可以看到成功设置系统属性,说明内核命令行参数注入成功,确定MOTO X受CVE-2016-10277漏洞的影响。

0x03 漏洞利用

通过该漏洞的命令行注入,我们可以向内核命令行注入众多参数,而这些参数又会在OS启动阶段多个地方被引用,因此该漏洞的攻击面是很广的,这里我们主要尝试能否通过该漏洞进行root提权。我们首先简单介绍下手机的启动过程,找到其中的利用点。

1) Android手机的Secure Boot过程

MOTO系列的手机大部分使用高通芯片,而高通芯片的手机大致启动过程如下:

[Primary Bootloader (PBL)] 
`-.
   [Secondary Bootloader (SBL)]
  `-.
    [Applications Bootloader (ABOOT)]
    `-.      
      [{boot,recovery}.img]
      |-- Linux Kernel
      `-- initramfs
          `-.
            [system.img]

手机开机后,首先启动的是bootloader,而bootloader又大致分为3个阶段,最先启动的是PBL,然后是SBL、ABOOT,最后通过ABOOT从boot.img或recovery.img中加载linux kernel和initramfs,进入系统加载阶段。initramfs是一个内存文件系统,bootloader一般会从固定的内存地址中加载,系统启动后会挂载到rootfs,即根目录/。initramfs包含很多重要文件,包括系统启动后第一个用户态进程init、服务启动脚本init.rc、selinux策略文件sepolicy、adbd程序等。如果我们能够让系统启动时加载我们构造的initramfs,那么我们就可以在这里面做很多劫持动作。而CVE-2016-10277的一个攻击面就是通过注入内核命令参数控制手机启动时的initramfs加载地址,加载我们指定的initramfs。

2) 通过参数注入劫持initramfs加载

通过CVE-2016-10277漏洞我们可以向内核注入initrd参数,该参数控制了initramfs的内存加载地址,参数形式如下:

initrd=<initramfs_address>,<initramfs_size>

首先我们测试是否可以劫持initramfs的加载地址,命令如下:

fastboot oem config fsg-id "a initrd=0x12341234,1024"
fastboot continue

执行命令后我们发现手机进入无限循环启动,无法进入系统,手机已崩溃,说明initrd参数起到了作用。为了验证能否顺利劫持initramfs加载,我们还需要找到可用的initramfs,并且找到向内存注入可控initramfs的方法。

由于不同的手机系统固件不一样,initramfs也不通用,我们只有通过网上下载的对应系统固件来提取initramfs。下载固件后解压缩找到boot.img,使用imgtool工具提取内核文件:

这里的ramdisk即是我们要找得initramfs。接下来我们想办法向内存中注入我们的ramdisk,可通过如下命令:

  fastboot flash thor ramdisk

我们向bootloader flash一个不存在image,虽然不能刷入,但是ramdisk肯定已经存在于手机内存中某个位置,接下来我们需要的就是找到这个位置。ABOOT二进制文件中有一个target_get_scratch_address函数,该函数返回的地址就是downloaded image存在的地址,所以我们通过IDA查看ABOOT文件就能够找到该地址。

ABOOT文件存在于bootloader中,提取固件中的bootloader.img,使用imgtool提取却出错了:

用010editor查看,看到了aboot的存在,但是bootloader.img应该是做了定制,不是普通的image文件。

使用谷歌大法,找到了一个专门用于提取moto image文件的python脚本https://github.com/laginimaineb/unpack_motoboot:

成功提取aboot文件后,放入IDA查看,由于没有删掉符号信息,可以快速定位到target_get_scratch_address函数:

我们从而得到flash image时image在内存中的地址为:0x11000000。综上,我们终于可以尝试劫持initramfs的加载:

不幸的是,手机依然无限循环重启。问题出在什么地方的?由于我们看不到任何启动时打印的信息,也不知从何入手。漏洞的发现者做出了一个猜测,有可能是flash image后,手机的启动过程中污染了我们发送的initramfs,导致initramfs被破坏。因此,我们需要将控制的initramfs填充,将真正的initramfs放到高地址的内存中:

.--------------------------------.----------------------.
| Physical Address               | Data                 |
|--------------------------------|----------------------|
| SCRATCH_ADDR                   | Corrupted PADDING    | 
| SCRATCH_ADDR + sizeof(PADDING) | Controlled initramfs |
`--------------------------------'----------------------'

我们选择padding的数据长度为32MB,

这次终于成功启动了系统,说明我们成功劫持了initramfs:

3) 构造initramfs获取root权限

成功劫持了initramfs后,我们需要想办法替换或修改initramfs中的文件来进行root提权。我们首先解压缩initramfs,它是一个cpio打包、gzip压缩的文件:

我们在sbin目录下看到了adbd二进制文件,它是我们我们执行adb shell时的服务程序。

我们想要root提权,一种方法就是patch adbd程序,让adb shell直接以root权限执行,而不是降权执行。在AOSP的adbd源码中我们看到,只要我们patch掉should_drop_privileges的执行,那么就能让adb shell以root权限执行。

但是,我们将adbd放入IDA一看,发现strip掉了函数符号,IDA在ARM64下没法F5,而且厂商在AOSP基础上做了很多定制,导致使用strings找特征都不好使。

如果要直接patch adbd程序估计得花很多时间逆向分析,这里我们走一下捷径,直接分析https://github.com/alephsecurity/initrootpatch后的adbd,然后对比原来的adbd程序,分析patch点,最后根据32位程序来推测64位arm程序可能的patch点。事实证明这是一条快速通道,我们很快就对比找到了patch点:

一共两处patch点,根据patch点的结构,我们在64位adbd中找到相似的patch点:

于是我们patch掉这两个地方,用patch后的adbd替换原来initramfs中的程序,重新打包运行,adb shell直接就是root权限:

通过类似的方法,我们还可以patch init程序,关掉selinux。

0x04 总结

CVE-2016-10277是一个比较有意思的漏洞,原理不复杂,只是一个简单的命令行参数注入,但是它的攻击面却很广,危害也很大。我们在复现该漏洞的利用过程中,经历了非常曲折的一个过程。本来漏洞发现者已经给出了MOTO G4、G5手机可用的exploit,但是我们的手机是MOTO X,原来的exp都没法用,只有自己摸索漏洞利用过程。在研究过程学习了secure boot、aboot、selinux等知识,该漏洞的利用覆盖了很广的知识面,值得研究。

本文分享自微信公众号 - FreeBuf(freebuf),作者:thor123

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-06-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 网络爬虫暗藏杀机:在Scrapy中利用Telnet服务LPE

    网络抓取框架中使用最多的莫过于是scrapy,然而我们是否考虑过这个框架是否存在漏洞妮?5年前曾经在scrapy中爆出过XXE漏洞,然而这次我们发现的漏洞是一个...

    FB客服
  • 利用PowerShell Empire实现Word文档DDE攻击控制

    ? 近期,有安全人员发现了一种DynamicData Exchange (DDE)协议绕过MSWord和MSExcel宏限制,不需使用MSWord和MSExc...

    FB客服
  • 日志标准化解析的关键内容

    在很多安全分析类产品建设的过程中都会涉及到关联分析,比如日志分析、soc、态势感知、风控等产品。之前的文章中阐述过五种最常见的关联分析模型,在文中也介绍了:要想...

    FB客服
  • Keras Pytorch大比拼

    对于许多数据科学家、工程师和开发人员来说,TensorFlow是他们深度学习框架的第一选择。TensorFlow 1.0于2017年2月发布,至少可以说,它不是...

    云水木石
  • Android性能优化(一)之启动加速35%

    随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战...

    用户2898788
  • Android性能优化之启动加速35%

    随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战...

    Android技术干货分享
  • Thread、ThreadPool、Task、Parallel、Async和Await基本用法、区别以及弊端

    ThreadPool是Thread的一个升级版,ThreadPool是从线程池中获取线程,如果线程池中又空闲的元素,则直接调用,如果没有才会创建,而Thread...

    Edison.Ma
  • C#/.NET基于Topshelf创建Windows服务的守护程序不显示UI界面的问题分析和解决方案

    C#/.NET基于Topshelf创建Windows服务的守护程序作为服务启动的客户端桌面程序不显示UI界面的问题分析和解决方案

    Rector
  • Confluence 6 MBeans 原

    你可以使用下面的 Confluence MBeans  来实时查看你 Confluence 实例运行的实时信息。

    HoneyMoose
  • python 多线程 条件condition(并行编程 6)

    class Consumers(threading.Thread): def init(self): threading.Thread.init(self)

    用户5760343

扫码关注云+社区

领取腾讯云代金券