編輯:關於Android編程
繼上一次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除了通過自簽名的方式,我們還可以采用由CA頒發私鑰證書進行簽發。采用這種方式,最終APK中的公鑰證書中,就會包含證書鏈。這種方式跟簽名名的主要區別是最終的公鑰證書中,Issuer和Subject是不相同的,而且會存在多於一個證書,證書與證書之間是通過Issuer與Subject進行關聯的,Issuer負責對Subject進行認證,下面是證書的驗證示意圖:
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() + ); sb.append(Certificate issuer: + x509Cert.getIssuerDN() + ); sb.append(Certificate serial number: + x509Cert.getSerialNumber() + ); sb.append( ); } 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插件的: APK證書中是否包含Adobe簽名的證書,證書數據是寫死在代碼中的(PluginManager.SIGNATURE_1),這是Adobe使用的簽名APK申請了android.webkit.permission.PLUGIN權限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.“
private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates) { for (int i = 0; i < candidates.length; i++) { if (issuer.equals(candidates[i].getSubjectDN())) { return candidates[i]; } } return null; }
private static X509Certificate findCert(Principal issuer, X509Certificate[] candidates, X509Certificate subjectCert, boolean chainCheck) { for (int i = 0; i < candidates.length; i++) { if (issuer.equals(candidates[i].getSubjectDN())) { if (chainCheck) { try { subjectCert.verify(candidates[i].getPublicKey()); } catch (Exception e) { continue; } } return candidates[i]; } } return null; }Fix後的代碼,添加了subjectCert和chainCheck兩個參數,添加了證書鏈的驗證。
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 輸入的密鑰口令 (如果和密鑰庫口令相同, 按回車):
通過這片文章可以回答以下兩個問題1、為啥EventBus的事件處理方法必須申明為Public?但是我用protected也是OK的2、粘性事件的原理,為啥發送多次Even
Android Design Support Library使用詳解Google在2015的IO大會上,給我們帶來了更加詳細的Material Design設計規范,同時
微信朋友圈現在比較亂,一堆微商把裡面弄得烏煙瘴氣亂七八糟,但是有時候有些內容還是值得認可的,我們最好的支持方式就是轉發了,那麼微信朋友圈怎麼轉發?微信朋友圈
先看效果圖圓面的繪制: package test.com.opengles8_1;import java.nio.ByteBuffer;import java.