加载中…
个人资料
行者无疆-超越
行者无疆-超越
  • 博客等级:
  • 博客积分:0
  • 博客访问:23,556
  • 关注人气:1
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
正文 字体大小:

Android签名漏洞分析

(2014-04-23 19:41:33)
标签:

android

安全

签名漏洞

it

分类: Android安全

Android的签名在理论上可以防止别人破坏了软件后(例如加入恶意代码)还能以你的名义发布。但是Android的签名机制最近接连暴露了两个漏洞,导致整个签名机制形同虚设。

第一个漏洞是由国外的安全公司 Bluebox Security发现的,这个漏洞自 Android 1.6以来就一直存在,号称对 99% android设备造成影响。恶意软件制作者可以在不破坏原有APK签名的前提下,利用这个漏洞来修改 APK 的代码并绕开Android应用的签名验证机制。

这个漏洞的原理是安装APK文件时,若APK包中同时存在着两个classes.dex,解压时读到第二个classes.dex时会覆盖掉第一个。这样实际进行签名检验的是第二个classes.dex。但是在运行时又是执行的第一个classes.dex,所以只要设法在一个APK文件中放置两个classes.dex,并使它们按照恶意classes.dex在前,正常classes.dex在后的顺序出现在文件中,就可以绕开签名检验并安装成功。

这段出问题的代码位于libcore/luni/src/main/java/java/util/zip/ZipFile.java中,让我们一起看看下面这段从版本4.2.2中摘录的代码:

private void readCentralDir() throws IOException {

   ......  

   // Seek to the first CDE and read all entries.

   RAFStream rafs = new RAFStream(mRaf, centralDirOffset);

   BufferedInputStream bin = new BufferedInputStream(rafs, 4096);

   byte[] hdrBuf = new byte[CENHDR]; // Reuse the same buffer for each entry.

   for (int i = 0; i < numEntries; ++i) {

        ZipEntry newEntry = new ZipEntry(hdrBuf, bin);

        mEntries.put(newEntry.getName(), newEntry);

    }

}

很明显,最后这段for循环的代码有问题,循环中读压缩包的内容并逐项加入到mEntries中,而mEntries是一个类型为LinkedHashMap的变量,调用put函数时如果有重名的项,会覆盖掉第一项。

下面再看看版本4.4.1中的代码,比较一下就知道Google是如何修复这个漏洞了。

private void readCentralDir() throws IOException {

   ......   

   RAFStream rafStream = new RAFStream(raf, centralDirOffset);

   BufferedInputStream bufferedStream = new BufferedInputStream(rafStream, 4096);

   byte[] hdrBuf = new byte[CENHDR]; // Reuse the same buffer for each entry.

   for (int i = 0; i < numEntries; ++i) {

      ZipEntry newEntry = new ZipEntry(hdrBuf, bufferedStream);

      if (newEntry.localHeaderRelOffset >= centralDirOffset) {

           throw new ZipException("Local file header offset is after

central directory");

      }

      String entryName = newEntry.getName();

      if (entries.put(entryName, newEntry) != null) {

          throw new ZipException("Duplicate entry name: " + entryName);

      }

   }

}

新的代码中会先检查entries中是否已经有同名的项,如果有会抛出异常。

可能有人会感兴趣,如何制造一个这样的apk文件呢?其实很简单,这里就不细说了,毕竟这里不是在教大家制造恶意程序。当然检测这种恶意程序也很简单,只要发现一个apk中有两个classes.dex就可以判定,正常的apk文件不会包含两个classes.dex文件。

第二个Andorid签名漏洞最早由国内的安全team发现并提交给GoogleGoogle很快修复了该漏洞。这个漏洞利用了Android在签名验证过程中,对Zip文件相应16位数的读取时,没有考虑到大于2^15的情况。这样在将用short型表示的块大小转换成int型时,会将大于2^15的数转换成int型的负数。但是在native层执行时,并不会出错。因为javaint , short, long都是有符号数,而不像C/C++里还有无符号书。具体的漏洞原理就不分析了。


0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有