继上一次Masterkey漏洞之后,Bluebox在2014年7月30日又公布了一个关于APK签名的漏洞——FakeID,并打算在今年的Blackhack上公布更详细的细节,不过作者Jeff Forristal在文中已经给出了不少提示,另外申迪的《FakeID签名漏洞分析及利用》也做了相关介绍。由于其中涉及的知识点较多,所以有部分朋友估计还没有看明白,所以我打算写一篇更详细漏洞分析解说,希望对大家有帮助。
所有者: 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
<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(); }
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看到这里,相信有些朋友已经懂了,那么下面的内容就可以不用看了,如果还是有疑问,那请耐心再往下看吧。
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插件的:
”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.“
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; }
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; }
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 []:
输入密钥库口令: 再次输入新口令: 您的名字与姓氏是什么? [Unknown]: 简行 您的组织单位名称是什么? [Unknown]: 简行之旅 您的组织名称是什么? [Unknown]: 简行之旅 您所在的城市或区域名称是什么? [Unknown]: 杭州 您所在的省/市/自治区名称是什么? [Unknown]: 浙江 该单位的双字母国家/地区代码是什么? [Unknown]: CH CN=简行, OU=简行之旅, O=简行之旅, L=杭州, ST=浙江, C=CH是否正确? [否]: y 输入 <client> 的密钥口令 (如果和密钥库口令相同, 按回车):