En

庖丁解牛--Android 第三个Master Key漏洞揭秘

作者:dragonltx[TSRC]公布时间:2013-11-06阅读次数:18003评论:0

分享

0x0 前言

       
        Android
系统Master Key漏洞一波未平一波又起,昨天,国外安全研究人员爆料Android系统存在第三个Master Key漏洞,黑客可以通过该漏洞完成控制我们的手机。目前,Google官方已经修复了该漏洞,但是由于Android系统更新的推动力更多的来自于各个设备生产商,因此补丁的推送滞后非常严重。我们在这里提醒大家,下载应用要到正规的市场去下载。


0x1 庖丁解牛

        该漏洞的主要原理是:android在解析Zip包时,没有校验ZipEntry和Header中的FileNameLength是否一致。

 

0x1.1 ZIP格式的文件结构

        在了解漏洞的原理前,先熟悉下zip格式的文件结构。

        如果一个压缩包文件里有多个文件,可以认为每个文件都是被单独压缩,然后再拼成一起。

        一个 ZIP 文件由三个部分组成:压缩源文件数据区+压缩源文件目录区+压缩源文件目录结束标志,如下图:

                      

                                          图 1
1)文件头(压缩源文件目录区)在文件末尾,即图1中的FileHeader,记录了索引段的偏移、大小等等。

2)数据段(压缩源文件数据区)在文件开头,即图1中的Local Header,记录了数据的一些基本信息,可以用来跟File Header中记录的数据进行比较,保证数据的完整性。

3)Local Header还包含了文件被压缩之后的存储区,即图1中的Data区域。

4)图2和图3为Local Header(图2中的ZIPFILERECORD)和File Header(图3中的ZIPDIRENTRY)的数据对比,两者数据是一致的。


                               图2


                              图3

0x1.2 漏洞产生原因

        先来看一下是如何定位到Local Header中的Data数据:


off64_t dataOffset = localHdrOffset +

                             kLFHLen +

                             get2LE(lfhBuf + kLFHNameLen) +

                             get2LE(lfhBuf + kLFHExtraLen);

        Data的偏移是通过Header的起始偏移+Header的大小(固定值)+Extra data的大小+文件名的大小,如图4

                              图4


        回头看一下,java在获取Data偏移的处理,在读取Extra data的长度的时候,它已经预存了文件名在FileHeader中的长度。


// We don't know the entry data's start position. 
// All we have is the position of the entry's local 
// header. At position 28 we find the length of the 
// extra data. In some cases this length differs 
// from the one coming in the central header. 

RAFStream rafstrm = new RAFStream(raf, 
         entry.mLocalHeaderRelOffset + 28); 
 DataInputStream is = new DataInputStream(rafstrm); 
int localExtraLenOrWhatever = 
         Short.reverseBytes(is.readShort()); 
 is.close(); 
// Skip the name and this "extra" data or whatever it is: rafstrm.skip(entry.nameLength + localExtraLenOrWhatever);


        漏洞就在这里产生了,如果Local Header中的FileNameLength被设成一个大数,并且FileName的数据包含原来的数据,File Header中的FileNameLength长度不变,那么底层C++运行和上层Java运行就是不一样的流程。

C++ Header 64k Name Data 
+--------> +----------------------> +----------> 
length=64k classes.dex dex\035\A... dex\035\B... 
+--------> +---------> +----------> 
Java Header 11 Name Data


        如上面所示,底层C++的执行会读取64k的FileName长度,而Java层由于是读取File Header中的数据,FileName的长度依旧是11,于是Java层校验签名通过,底层执行会执行恶意代码。

 

漏洞修复方案:

校验Local Header和File Header中的FileNameLength是否一致

int length = Short.reverseBytes(raf.readShort()) & 0xffff; 
if (length != length.getInt(entry)) 
             throw new ZipException();


0x2 后记

        从Android系统的这3个MasterKey漏洞,我们进行了如下反思:

1、手机厂商的安全意识有待加强

        由于Android系统的开源特性,注定了各大手机产商百花齐放,市面上的Android系统安全性参差不齐。更为严重的是,如果Android系统爆出系统漏洞,由于各大手机产商安全意识薄弱,导致补丁推送速度严重跟不上。因此,国内手机厂商的安全意识有待加强,真真正正用户至上。

2、开发者安全意识有待加强

        从这个3个Master Key漏洞管中窥豹,都是由于开发者的安全意识薄弱,导致产生严重的逻辑漏洞。同时,由于Android系统补丁推送的滞后性,业务需要预备一套应对系统漏洞的应对方案。以这个漏洞为例,业务可以对自己的安装包进行校验,防止被黑客恶意利用。后续我们会在这方面进行改进、完善,并且会与业界进行交流,分享我们的成果。

 

0x3 参考

YetAnother Android Master Key Bug

 


评论留言

提交评论 您输入的漏洞名称有误,请重新输入