通用簽名風(fēng)險(xiǎn)簡介
1.1 Android應(yīng)用簽名機(jī)制
阿里聚安全漏洞掃描器有一項(xiàng)檢測服務(wù)是檢測APP的通用簽名風(fēng)險(xiǎn)。Android系統(tǒng)要求安裝的應(yīng)用必須用數(shù)字證書進(jìn)行簽名后才能安裝,并且簽名證書的私鑰由應(yīng)用開發(fā)者保存。簽名證書的生成也由開發(fā)者自己生成。在應(yīng)用安裝時(shí)會校驗(yàn)包名(package name)和簽名,如果系統(tǒng)中已經(jīng)存在了一個(gè)相同的包名和簽名的應(yīng)用,將會用新安裝的應(yīng)用替換舊的;如果包名相同但是簽名不同,則會安裝失敗。
為什么需要數(shù)字簽名?
數(shù)字簽名是防止要保護(hù)的內(nèi)容被篡改,用非對稱加密算法。先對要保護(hù)的內(nèi)容進(jìn)行消息摘要,用私鑰對消息摘要進(jìn)行加密,生成數(shù)字簽名,將數(shù)字簽名和要保護(hù)的內(nèi)容一起分發(fā)出去。 內(nèi)容接收者用公鑰對數(shù)字簽名解密得到發(fā)送者給的消息摘要A,內(nèi)容接收者對接收到的內(nèi)容進(jìn)行用相同的消息摘要算法處理得到消息摘要B,對比A和B是否相同,來判定傳送的內(nèi)容是否被篡改。 正常的APK文件是個(gè)ZIP壓縮文件,除了應(yīng)用的可執(zhí)行文件、資源文件,還包括這些可執(zhí)行文件、資源文件的摘要信息,數(shù)字證書的公鑰信息等。并且通過這些簽名信息可以確定APP和其開發(fā)者的關(guān)系。
進(jìn)行簽名需要的工具有哪些?
對apk進(jìn)行簽名需要用到簽名證書和簽名工具。Android系統(tǒng)要求對APP進(jìn)行簽名的數(shù)字證書可以由開發(fā)者自己生成。簽名工具有jarsigner和signapk。jarsigner是Java本身自帶的一個(gè)工具,他也可以對jar進(jìn)行簽名的;而signapk是專門為了Android應(yīng)用程序apk進(jìn)行簽名的工具。二者的區(qū)別是:jarsigner工具簽名時(shí)使用的是keystore簽名文件,signapk工具簽名時(shí)使用的是pk8,x509.pem文件。
簽名后的文件都有哪些?
應(yīng)用簽名完后在應(yīng)用的META-INF目錄下會有三個(gè)文件:
CERT.RSA、CERT.SF和MANIFEST.MF。
MANIFEST.MF中保存了所有其他文件的SHA1摘要并base64編碼后的值。
CERT.SF文件是對MANIFEST.MF文件中的每項(xiàng)中的每行加上“\r\n”后,再次SHA1摘要并base64編碼后的值(這是為了防止通過篡改文件和其在MANIFEST.MF中對應(yīng)的SHA1摘要值來篡改APK,要對MANIFEST的內(nèi)容再進(jìn)行一次數(shù)字摘要)。
CERT.RSA文件:包含了簽名證書的公鑰信息和發(fā)布機(jī)構(gòu)信息。
對安裝包的校驗(yàn)過程在源碼的frameworks/base/core/java/android/content/pm/PackageParser.java類中可以看到,具體可看阿里聚安全博客的另外一篇文章:Android5.1.1 – APK簽名校驗(yàn)分析和修改源碼繞過簽名校驗(yàn)。
1.2 通用簽名風(fēng)險(xiǎn)
什么是通用簽名?
搭建好Android開發(fā)環(huán)境后(使用Eclipse或Android Studio),對APK簽名的默認(rèn)密鑰存在debug.keystore文件中。在linux和Mac上debug.keystore文件位置是在~/.android路徑下,在windows目錄下文件位置是C:\user\用戶名.android路徑下。
除了debug.keystore外,在AOSP發(fā)布的Android源碼中,還有以下幾個(gè)證書是公開的,任何人都可以獲取,在源碼的build/target/product/security目錄中:
這幾個(gè)證書的作用:
testkey
Generic default key for packages that do not otherwise specify a key.
platform
Test key for packages that are part of the core platform.
shared
Test key for things that are shared in the home/contacts process.
media
Test key for packages that are part of the media/download system.
verity
Test Key for verifiedboot system imagein Android Lollipop. Sign boot.img,sign verity metadata in system.img.
通用簽名風(fēng)險(xiǎn):
(1)如果攻擊者的應(yīng)用包名與目標(biāo)應(yīng)用相同,又使用了相同的密鑰對應(yīng)用進(jìn)行簽名,攻擊者的應(yīng)用就可以替換掉目標(biāo)應(yīng)用;
(2)另外目標(biāo)應(yīng)用的自定義權(quán)限android:protectionlevel為“signature”或者“signatureOrSystem”時(shí),保護(hù)就形同虛設(shè);
(3)如果設(shè)備使用的是第三方ROM,而第三方ROM的系統(tǒng)也是用AOSP默認(rèn)的簽名,那么使用如果使用系統(tǒng)級簽名文件簽名過的應(yīng)用,權(quán)限就得到了提升。
對于普通開發(fā)者如果自己的簽名證書泄露也可能發(fā)生(1)、(2)條所提到的風(fēng)險(xiǎn)。
通用簽名風(fēng)險(xiǎn)示例
使用通用簽名的公開案例非常少,不過我們阿里聚安全漏洞掃描器還是發(fā)現(xiàn)了一些應(yīng)用使用了通用簽名,掃描結(jié)果數(shù)據(jù)庫中查到曾經(jīng)有819個(gè)APP使用了AOSP的簽名證書(排查了幾個(gè)APP的最新版,但都已經(jīng)用了新的簽名;也不排除應(yīng)用被惡意攻擊者反編譯重打包后使用通用簽名證書簽名)。 另外還有不少私有簽名證書泄露、濫用的(使用通用簽名證書其實(shí)就相當(dāng)于泄露了簽名證書)情況。
以烏云公開的WooYun-2014-67027為例,有安全研究人員發(fā)現(xiàn)有一個(gè)數(shù)字證書簽名被很多銀行的手機(jī)客戶端所使用。與此同時(shí)還發(fā)現(xiàn)了幾款個(gè)人開發(fā)者類應(yīng)用也使用了此證書簽名。而這種數(shù)字簽名被濫用的行為存在極大的安全隱患。
解壓應(yīng)用安裝包,可用keytool查看應(yīng)用的簽名證書信息:
keytool -printcert -v -file META-INF/CERT.RSA
經(jīng)挖掘和分析,研究人員發(fā)現(xiàn)目前共有23款不同銀行手機(jī)銀行客戶端使用該簽名:
在應(yīng)用市場內(nèi),目前共發(fā)現(xiàn)6款個(gè)人開發(fā)的應(yīng)用同時(shí)使用該數(shù)字證書簽名:
事情發(fā)生的原因是銀行的外包開發(fā)管理不嚴(yán),不同銀行的APP居然用同樣的數(shù)字證書簽名,并且開發(fā)者還將證書用于了個(gè)人APP的開發(fā)中。如果簽名證書被惡意攻擊者獲取,可以編寫安裝是能直接替換掉這些銀行客戶端的惡意APP。
還可以使用AOSP通用簽名提升應(yīng)用權(quán)限:
本人直接編譯AOSP源碼得到的ROM,使用AOSP的默認(rèn)證書,在設(shè)置->關(guān)于手機(jī),版本號中可查看到:
對于普通的用默認(rèn)debug.keystore證書簽名的App,如果在AndroidManfiest.xml的manifest節(jié)點(diǎn)加入android:sharedUserId=”android.uid.system”這個(gè)屬性,安裝時(shí)會提示錯(cuò)誤:
如果對app-debug.apk使用AOSP提供的platform.x509.pem和platform.pk8重新簽名,則可以安裝成功:
查看應(yīng)用的進(jìn)程屬性,已是system用戶組。
目前有不少的第三方ROM使用的AOSP提供的默認(rèn)簽名(見參考[4]的論文中所提)。
阿里聚安全對開發(fā)者建議
(1)上線前用阿里聚安全的漏洞掃描器進(jìn)行一下檢查。
阿里聚安全的漏洞掃描器目前已能檢查出通用簽名風(fēng)險(xiǎn),未來可能增加檢測證書是否泄漏風(fēng)險(xiǎn)。還可以發(fā)現(xiàn)其他安全風(fēng)險(xiǎn)。
(2) 生成自己專有的簽名證書,證書分類使用。 使用keytool工具生成.keystore的數(shù)字證書:
keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
使用jarsigner工具對打包好的APK進(jìn)行簽名:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1-keystore my-release-key.keystore my_application.apk alias_name
使用openssl生成pk8和x509.pm的證書,參考如下:
使用signapk工具和pk8、x509.pm證書對打包好的APP簽名:
java -jar signapk.jar platform.x509.pem platform.pk8 input.apk output.apk
或者Gradle打包配置設(shè)置:
(3)做好安全培訓(xùn),規(guī)范開發(fā)流程,證書之類的統(tǒng)一管理。
(4)個(gè)人開發(fā)者在往開源平臺上傳代碼時(shí),注意不要將簽名證書的私鑰上傳。
搜了下github,有不少開發(fā)者將其release版的keysotre上傳了,并且在gradle文件上寫上了keystore的訪問密碼。如下: