趋势科技近日发现了Android调试器Debuggerd中的漏洞,该漏洞可以获取设备内存中的数据,影响系统包括Android 4.0 Ice Cream Sandwich(冰淇淋三明治)到Lollipop(棒棒糖)。

一个构造精巧的ELF(Executable and Linkable Format)文件可以导致调试器崩溃,然后通过tombstone文件和对应的logd日志文件暴露内存内容。这可以被用于拒绝服务攻击,可以帮助绕过ASLR执行恶意代码。仅仅利用这个漏洞是无法进行代码执行的。但是通过这个漏洞暴露的信息可以和其他漏洞结合用于代码执行。

这个漏洞可以被恶意应用或者重新打包的应用利用。漏洞影响的系统版本包括Android 4.0 (Ice Cream Sandwich)到Lollipop(5.x),下一代的Android M已经修复了这个漏洞。

漏洞详情

导致漏洞的原因是在执行字符串复制命令时,Debuggerd会使用sym->st_name作为offset,而不进行错误检查。这个值可以轻易被恶意的ELF文件控制,它可以将offset值指向不可读取的内存,Debuggerd就会崩溃。如果不断崩溃就会造成拒绝服务攻击。如果精心构造offset就会使Debuggerd暴露相应的内存内容,Debuggerd会将它们存入dump和log文件中。
对于Android 5.0-5.1,漏洞出现在external/libunwind/src/elfxx.c:

    126       for (sym = symtab;
    127            sym < symtab_end;
    128            sym = (Elf_W (Sym) *) ((char *) sym + syment_size))
    129         {
    130           if (ELF_W (ST_TYPE) (sym->st_info) == STT_FUNC
    131           && sym->st_shndx != SHN_UNDEF)
    132         {
    133           if (tdep_get_func_addr (as, sym->st_value, &val) < 0)
    134             continue;
    135           if (sym->st_shndx != SHN_ABS)
    136             val += load_offset;
    137           Debug (16, "0x%016lx info=0x%02x %s\n",
    138              (long) val, sym->st_info, strtab + sym->st_name);
    139
    140                   /* ANDROID support update */
    141                   if ((Elf_W (Addr)) (ip - val) < *min_dist
    142                       && (Elf_W (Addr)) (ip - val) < sym->st_size)
    143                   /* End of ANDROID update */
    144             {
    145               *min_dist = (Elf_W (Addr)) (ip - val);
    146               strncpy (buf, strtab + sym->st_name, buf_len);  //st_name的地址可能被恶意ELF轻易控制
    147               buf[buf_len - 1] = &#039;&#039;;
    148               ret = (strlen (strtab + sym->st_name) >= buf_len
    149                  ? -UNW_ENOMEM : 0);
    150             }
    151         }
    152         }

想重现漏洞,就要用到一个能够导致崩溃的ELF文件。我们可以通过修改符号偏移做到。ELF被放入APK后,它就会被循环执行。之后就会触发漏洞,见下图:

在Android旧版本中也可以发现类似的问题(特别是4.x版本,如Ice Cream Sandwich, Jelly Bean和KitKat)。在这些版本中用的不是libunwind第三方库。在Android 4.0中,漏洞存在于system/core/debuggerd/symbol_table.c:

    155     int j = 0;
    156     if (dynsym_idx != -1) {
    157         // …and populate them
    158         for(i = 0; i < dynnumsyms; i++) {
    159             if(dynsyms[i].st_shndx != SHN_UNDEF) {
    160                 table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name);//st_name没有经过检查就被使用了
    161                 table->symbols[j].addr = dynsyms[i].st_value;
    162                 table->symbols[j].size = dynsyms[i].st_size;
    163                 XLOG2(“name: %s, addr: %x, size: %x\n”,
    164                     table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size);
    165                 j++;
    166             }
    167         }
    168     }
    169
    170     if (sym_idx != -1) {
    171         // …and populate them
    172         for(i = 0; i < numsyms; i++) {
    173             if((syms[i].st_shndx != SHN_UNDEF) &&
    174                 (strlen(str+syms[i].st_name)) &&
    175                 (syms[i].st_value != 0) && (syms[i].st_size != 0)) {
    176                 table->symbols[j].name = strdup(str + syms[i].st_name);//st_name没有经过检查就被使用了
    177                 table->symbols[j].addr = syms[i].st_value;
    178                 table->symbols[j].size = syms[i].st_size;
    179                 XLOG2(“name: %s, addr: %x, size: %x\n”,
    180                     table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size);
    181                 j++;
    182             }
    183         }
    184     }

而在Android 4.1-4.4中,漏洞存在于system/core/libcorkscrew/symbol_table.c:

    150     size_t symbol_index = 0;
    151     if (dynsym_idx != -1) {
    152         // …and populate them
    153         for (int i = 0; i < dynnumsyms; i++) {
    154             if (dynsyms[i].st_shndx != SHN_UNDEF) {
    155                 table->symbols[symbol_index].name = strdup(dynstr + dynsyms[i].st_name);//st_name没有经过检查就被使用了
    156                 table->symbols[symbol_index].start = dynsyms[i].st_value;
    157                 table->symbols[symbol_index].end = dynsyms[i].st_value + dynsyms[i].st_size;
    158                 ALOGV(”  [%d] ‘%s’ 0x%08x-0x%08x (DYNAMIC)”,
    159                         symbol_index, table->symbols[symbol_index].name,
    160                         table->symbols[symbol_index].start, table->symbols[symbol_index].end);
    161                 symbol_index += 1;
    162             }
    163         }
    164     }
    165
    166     if (sym_idx != -1) {
    167         // …and populate them
    168         for (int i = 0; i < numsyms; i++) {
    169             if (syms[i].st_shndx != SHN_UNDEF
    170                     && str[syms[i].st_name]
    171                     && syms[i].st_value
    172                     && syms[i].st_size) {
    173                 table->symbols[symbol_index].name = strdup(str + syms[i].st_name);//st_name is type of uint32_t not be checked
    174                 table->symbols[symbol_index].start = syms[i].st_value;
    175                 table->symbols[symbol_index].end = syms[i].st_value + syms[i].st_size;
    176                 ALOGV(”  [%d] ‘%s’ 0x%08x-0x%08x”,
    177                         symbol_index, table->symbols[symbol_index].name,
    178                         table->symbols[symbol_index].start, table->symbols[symbol_index].end);
    179                 symbol_index += 1;
    180             }
    181}
    182     }

趋势科技的研究员已经在今年4月27日将漏洞提交给了Google。5月15日Android Open Source Project (AOSP)代码中发布了一个针对这个漏洞的补丁。

*参考来源:趋势科技,译/Sphinx,文章有修改,转载请注明来自Freebuf黑客与极客(FreeBuf.COM)

源链接

Hacking more

...