Android证书验证存漏洞 开发者身份信息可被篡改

近期在国内网易,雷锋网等网站爆出谷歌市场上的索尼官方的备份与恢复应用“Backup and Restore”被黑的消息。新闻显示:目前索尼官方的备份与恢复应用“Backup and Restore”已经被黑客彻底破解;甚至在Google Play商店里该应用的所有权都被黑客修改;目前仍不清楚使用破解修改版本的应用,会否对用户造成损害;建议用户尽量避免使用,删除已下载的应用;目前在 Google Play上应用管理权都归于“HeArt HaCkEr Group”,开发者信息显示“Nirav Patel Kanudo”。

 
阿里钱盾专家分析认为,Android证书验证机制存在漏洞,开发者身份信息可以任意篡改,而不会影响应用APK的安装、升级、运行等操作。针对这一情况,阿里钱盾(qd.alibaba.com)团队也专门进行了研究和提出了相应的解决措施。
 
Android证书验证机制
 
首先,详细说明Android应用程序安装文件APK的证书验证机制。
 
1. 基本算法
 
(1)消息摘要 -Message Digest
 
简称摘要,在消息数据上,执行一个单向的Hash函数,生成一个固定长度的Hash值,也称为数字指纹,消息摘要有以下特点:
 
1. 通过摘要无法推算得出消息本身。
 
2. 如果修改了消息,那么摘要一定会变化(除开碰撞情况)。
 
3. 消息摘要只能保证消息的完整性,并不能保证消息的不可篡改性。
 
在Android证书里,一般采用SHA-1算法来生成摘要值。
 
(2)数字签名 - Signature
 
消息的发送者用自己的私钥对消息摘要进行加密,产生一个加密后的字符串,称为数字签名。因为发送者的私钥保密,可以确保别人无法伪造生成数字签名,也是对信息的发送者发送信息真实性的一个有效证明。数字签名是 非对称密钥加密技术 + 数字摘要技术 的结合。
 
数字签名技术是将信息摘要用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的信息摘要,然后接收者用相同的Hash函数对收到的原文产生一个信息摘要,与解密的信息摘要做比对。如果相同,则说明收到的信息是完整的,并且是由该发送者生成的(因为只有发送者才拥有对应的私钥)。
 
(3)数字证书 - Certificate
 
数字证书是一个经证书授权中心数字签名的包含公开密钥拥有者信息以及公开密钥的文件。
 
证书包含的有效信息有:证书版本、证书序号、证书颁发机构、证书有效期、证书拥有者和拥有者公钥,以及证书颁发机构对该证书的签名。
 
需要注意的是Android APK中的CERT.RSA证书可以是自签名的,并不需要这个证书是第三方权威机构发布或者认证的,用户可以在本地机器自行生成这个自签名证书。
当使用某证书时,需要验证该证书的合法性:使用证书颁发者的公钥,然后对整个证书(除了证书数字签名以外)采用给定的证书签名算法计算,然后将计算结果同证书数字签名对比,相同则可以证明该证书确实由证书颁发者颁发的合法证书;不同则说明有篡改存在,证书不合法。
 
2. Android证书组成
 
APK文件实际上是一个压缩文件包,我们将文件后缀.APK修改为.zip,可以使用解压缩软件直接打开。如weixin.APK
 
 
(1) MANIFEST.MF
 
遍历APK包中除了META-INF\ 文件夹以外的所有文件,利用SHA1算法生成这些文件的消息摘要,然后转化为对应的base64编码。MANIFEST.MF存储的是文件的摘要值,保证完整性,防止文件被篡改。weixin的MANIFEST.MF:
 
Manifest-Version: 1.0
 
Created-By: 1.7.0_45 (Oracle Corporation)
 
Name: r/t/a3k.xml
 
SHA1-Digest: c6GfCzDzRo75w7HwMzjcPXGi++I=
 
Name: r/v/a1m.png
 
SHA1-Digest: Ao27xq4nYyBR5Z0yG07pN0MtlKI=
 
……
 
(2) .SF
 
xx.SF文件(xx为使用者证书的自定义别名,默认为CERT,即CERT.SF),保存的是MANIFEST.MF的摘要值, 以及MANIFEST.MF中每一个摘要项的摘要值,然后转化成对应的base64编码。虽然该文件的后缀名.sf(SignatureFile)看起来是签名文件,但是并没有私钥参与运算,也不保存任何签名内容。
 
weixin的COM_TENC.SF:
 
Signature-Version: 1.0
 
SHA1-Digest-Manifest-Main-Attributes: sY6+RQ4DWdnxCfSpiwTT6GRIwA0=
 
Created-By: 1.7.0_45 (Oracle Corporation)
 
SHA1-Digest-Manifest: GduDrpyEw/pgWazHpioH6+7MyKo=
 
Name: r/t/a3k.xml
 
SHA1-Digest: b6IQQJD88w4yCVk0QHuy2cySHTE=
 
Name: r/v/a1m.png
 
SHA1-Digest: HqlAkc/TpMyeU/jhapu/Pxg1QLQ=
 
……
 
(3) .RSA / .DSA
 
.RSA / .DSA文件(后缀不同采用的签名算法不同,.RSA使用的是RSA算法, .DSA使用的是数字签名算法DSA,目前APK主要使用的是这两种算法),保存的是第二项.SF文件的数字签名,同时还会包括签名采用的数字证书(公钥)。特别说明,当使用多重证书签名时,每一个.sf文件必须有一个.RSA/.DSA文件与之对应,也就是说使用证书CERT1签名时有CERT1.SF和CERT1.RSA,同时采用证书CERT2签名时又会生成CERT2.SF和CERT2.RSA。
 
weixin的COM_TENC.RSA(解码后):
 
Certificate:
 
Data:
 
Version: 3 (0x2)
 
Serial Number: 1295447972 (0x4d36f7a4)
 
Signature Algorithm: sha1WithRSAEncryption
 
Issuer: C=86, ST=Guangdong, L=Shenzhen, O=Tencent Technology(Shenzhen) Company Limited, OU=Tencent Guangzhou Research and Development Center, CN=Tencent
 
Validity
 
Not Before: Jan 19 14:39:32 2011 GMT
 
Not After : Jan 11 14:39:32 2041 GMT
 
Subject: C=86, ST=Guangdong, L=Shenzhen, O=Tencent Technology(Shenzhen) Company Limited, OU=Tencent Guangzhou Research and Development Center, CN=Tencent
 
Subject Public Key Info:
 
Public Key Algorithm: rsaEncryption
 
Public-Key: (1024 bit)
 
Modulus:
 
…..
 
Exponent: 65537 (0x10001)
 
Signature Algorithm: sha1WithRSAEncryption
 
……
 
.SF Signature Algorithm: sha1WithRSAEncryption
 
……
 
.RSA文件包括证书和.SF签名2个部分,其中证书里面也有一个签名,是证书颁发者对该证书的签名。
 
对APK的证书签名具体原理和算法,可以参考
 
https://Android.googlesource.com ... ignAPK/SignAPK.java
 
3. Android证书验证机制
Android 系统不允许安装没有任何数字签名的应用APK程序,所有应用程序必须使用某个证书进行签名(一般为应用开发者自签名证书):
 
APK源文件,首先由应用开发者使用自己的私钥,对整个文件进行签名,生成上述的三个文件,然后打包成签名后的APK文件;然后发布到市场,图示是Google市场。
 
用户从市场下载APK安装文件,在真正安装APK前,会首先验证数字签名。具体步骤:
 
(1) 首先计算除META-INF\ 文件夹以外所有文件的SHA1摘要值,同MANIFEST.MF文件中的摘要值做比对。如果不同,则证明源文件被篡改,验证不通过,拒绝安装。
 
(2) 计算MANIFEST.MF的摘要值, 以及MANIFEST.MF中每一个摘要项的摘要值,同.SF文件中的摘要值做比对。如果不同,则证明.SF被篡改,验证不通过,拒绝安装。
 
(3) 从.RSA 文件中取出开发者证书,然后从证书中提取开发者公钥,用该公钥对.SF文件做数字签名,并将结果同.RSA文件中的.SF签名进行比对。如果不同,则验证不通过,拒绝安装。
 
存在的问题
 
2014年报出来的Fake ID漏洞,是对证书链的验证方法存在漏洞,没有对证书本身的签名进行验证(不同于.SF签名),场景:证书颁发者A对证书B进行签名,然后使用证书B对APK的.SF文件签名,而安装APK时仅仅验证了证书B对.SF文件的数字签名,而没有验证颁发者A对该证书B本身的数字签名。目前,GOOGLE已经对该漏洞进行了修复,但笔者认为,该修复并不完全:仅仅修复了证书链的认证方法,没有对自签名证书中的证书数字签名进行验证,存在着一定的问题。
 
代码段org.apache.harmony.security.utils. JarUtils:
 
191 // Signer is self-signed
 
192 if (signer.getSubjectDN().equals(signer.getIssuerDN())){
 
193 return (X509Certificate[])chain.toArray(new X509Certificate[1]);
 
194 }
 
当采用自签名证书时,Android直接跳过验证,将证书加入了合法证书列表。这导致攻击者拿到.RSA / .DSA文件后,可以对其中的证书(除了证书拥有者公钥之外)随意篡改,包括证书序号、证书有效期、证书拥有者名字等等。而Android在安装APK时,仅仅使用了证书中的公钥,其它信息未使用也未作任何验证,只要使用公钥验证.SF文件的数字签名通过就可以正常安装使用。
 
1. 证书有效期篡改
 
以weixin的COM_TENC.RSA证书为例,直接修改证书有效期(仅仅改动COM_TENC.RSA文件):
 
Certificate:
 
……
 
Validity
 
Not Before: Jan 19 14:39:32 2011 GMT
 
Not After : Jan 11 14:39:32 2011 GMT
 
……
 
很明显的证书有效期错误,结束时间比开始时间还早,但是修改后的APK依然可以正常安装、运行,因为COM_TENC.RSA文件里的公钥(证书的一部分)和.SF文件都没有修改,可以通过Android证书验证机制。
 
联想开来,某个已过期的证书依然可以使用,假如某个拥有高权限的证书已经过期,危害会很大。例如Adobe颁发过某个证书C(使用Adobe公钥签名该证书),然后证书C过期了,但是由于用Adobe的公钥验证该证书仍然可以通过(修复过的证书链认证可以通过,除非Adobe吊销它自己的证书),而Android并没有验证证书有效性,所以用证书C签过名的APK依然拥有Adobe的高权限。
 
2. 证书拥有者主体篡改
 
以weixin的COM_TENC.RSA证书为例,直接修改证书拥有者名字(仅仅改动COM_TENC.RSA文件):
 
Certificate:
 
……
 
Issuer: C=86, ST=Guangdong, L=Shenzhen, O=abcdefg Technology(Shenzhen) Company Limited, OU=abcdefg Guangzhou Research and Development Center, CN=abcdefg
 
Validity
 
Not Before: Jan 19 14:39:32 2011 GMT
 
Not After : Jan 11 14:39:32 2011 GMT
 
Subject: C=86, ST=Guangdong, L=Shenzhen, O=abcdefg Technology(Shenzhen) Company Limited, OU=abcdefg Guangzhou Research and Development Center, CN=abcdefg
 
……
 
将开发者信息修改为了abcdefg,但是修改后的APK依然可以正常安装、运行,因为COM_TENC.RSA文件里的公钥(证书的一部分)和.SF文件都没有修改,可以通过Android证书验证机制。
 
联想开来,开发者主体信息很容易修改,造成知识版权问题,例如可以把Google开发的APK的开发者证书信息修改成我自己的名字,扩大影响力;或者,把自己开发的恶意APK冠上Google的名字。
 
3. 证书吊销CRL
 
Android证书机制并没有引入CRL吊销机制,已经吊销但拥有合法签名的证书依然可以使用,和第一项证书过期类似(证书过期,也是吊销的一种方法)。
 
但是,证书吊销还有另外一个应用,当发现某个证书的私钥有泄露或是被破解时,业界常用的手法是吊销该证书,加入CRL列表,例如2012年发生的Yahoo Axis私钥泄露事件。在Android系统里,并没有采用证书吊销机制,设想场景:Adobe颁发过某个证书D(使用Adobe公钥签名该证书),然后证书D在使用过程中发生了私钥泄露,那么此时只有吊销Adobe自己的根证书才能真正使证书D失效,成本大而且会影响其他Adobe签过名的证书。
 
Google的态度
 
笔者就上述问题上报过Google Security。Google回复,证书机制只是用来认证开发者拥有该证书的私钥,并不验证证书本身的合法性(因为自签名系统,每个人都可以成为自己的证书颁发者)。而证书有效期问题,Google Play自己的市场有验证,但在Android系统里没有引进(为什么?),对其它第三方市场不保证。然后,证书吊销CRL机制,因为没有好的方法实现,所以没做。
 
笔者认为,目前可以加强的是自签名证书的验证机制(增加一行验证代码即可),对自签名证书的数字签名也使用自签名证书的公钥进行验证,可以杜绝对.RSA/ .DSA文件的任意篡改。
 
Hi Yichin,
 
The behavior you describe is working as intended. App signing certificates for Android are only designed to identify that the author of an app has the private key for that certificate, not to verify their actual identity. There is currently no way to effectively revoke a certificate used to sign an APK.
 
This is documented here: https://source.Android.com/devices/tech/security/
 
"Applications can be signed by a third-party (OEM, operator, alternative market) or self-signed. Android provides code signing using self-signed certificates that developers can generate without external assistance or permission. Applications do not have to be signed by a central authority. Android currently does not perform CA verification for application certificates."
 
There is also more information here:
 
http://developer.Android.com/tools/publishing/app-signing.html
 
Regarding expired certificates, we actually enforce that APKs published in Play not expire until 2033:
 
"If you plan to publish your apps on Google Play, the key you use to sign these apps must have a validity period ending after 22 October 2033. Google Play enforces this requirement to ensure that users can seamlessly upgrade apps when new versions are available."
 
Although, at this time, the Android platform itself does not enforce the validity period.
 
-jon
 
Sony官方系统应用伪造的原因分析
 
Google Play市场上出现了伪造的Sony官方系统应用,并且可以被用户覆盖升级本机的合法系统应用。Android应用的覆盖升级,前提要求是应用的覆盖前后2个版本拥有相同的开发者公钥(不是证书,仅仅是公钥),只要前后的2个公钥相同,Android默认前后2个开发者拥有相同的私钥,据此认定是同一个开发者。也就是说,伪造者和Sony使用的是相同的公钥。
 
伪造者使用的是同Sony相同的公钥,却可以将应用开发者身份信息随意修改,将Sony Mobile Communications修改成Nirav Patel Kanudo。如果Android对自签名证书也进行过验证,则可以杜绝这种行为,因为一旦证书拥有者被篡改,那么该证书的数字签名不可能通过验证。
 
由于新闻信息简短,而且伪造的APK已经下架(没有拿到样本),笔者做以下推论分析:
 
(1) Sony的Google账号可能有泄露,攻击者可以使用Sony账号在Google市场上传APK。
 
(2) Sony 私钥没有泄露。该APK仍然是官方出品的APK,但是被攻击者修改了证书文件里的证书拥有者信息,将Sony Mobile Communications修改成了Nirav Patel Kanudo。应用本身无害,用户使用没有问题。
 
(3) Sony私钥有泄露。攻击者修改了官方应用APK(可能植入恶意代码),然后使用Sony的私钥对修改后的APK重新打包签名,而且修改了证书文件里的证书拥有者信息(将Sony Mobile Communications修改成了Nirav Patel Kanudo),并上传到了Google Play。应用有害,用户使用有风险。
 
不管是以上哪种情况,可以确认的是自签名证书中的开发者身份信息可以任意修改,Android系统缺少对自签名证书里的数字签名的验证,仅仅实现了对.SF文件的签名验证。
 
Android市场目前严峻形势
 
1. 最权威的市场也可能存在仿冒的应用
 
作为Android手机最权威的官方应用市场,Google Play一直以来都是Android应用市场中最安全的市场之一。但本次被黑应用上架的市场正是谷歌市场,可见其在审核开发者信息的过程也存在漏洞。据此前阿里移动安全的研究分析,被黑和仿冒应用的风险普遍存在,有超过80%的热门应用都存在仿冒,且平均仿冒数量高达13个。若再将开发者信息的仿冒包含在内,仿冒应用的风险形式必将更加严峻。
 
在国内部分应用市场上,应用的开发者信息在应用查看,下载和安装的过程都不进行显示。且Android手机上是否允许非官方应用市场来源的应用的选项往往是打开的。国内Android的整体安全性更让人担忧。
 
2. 应用不可信?用户应该如何是好?
 
虽然本次事件不一定会造成严重风险,但因为Android应用安装的漏洞和Android应用市场的不规范,导致不可信应用非常普遍,用户还是需要引起注意,阿里钱盾专家提醒大家:
 
(1)涉及账户,资金的应用如淘宝,支付宝,微信等 尽量在官方网站进行应用下载。
 
(2)谨慎选择应用,并在手机上安装安全软件,防止自身信息的泄露。
 
(3)用户可以通过安装阿里钱盾,获得最重要的网购和资金安全保护。