Android官方开发文档Training系列课程中文版:Android的安全建议
原文地址:http://android.xsoftlab.net/training/articles/security-tips.html
Android系統(tǒng)內(nèi)置的安全策略可以有效的降低應(yīng)用程序的安全問(wèn)題。所以默認(rèn)創(chuàng)建的應(yīng)用程序已經(jīng)包含了一定程度的安全保護(hù)措施。
Android所包含的安全策略有:
- 應(yīng)用程序沙箱,它可以使APP的數(shù)據(jù)、代碼與其它APP相互隔離。
- 應(yīng)用程序框架對(duì)于常見(jiàn)防護(hù)措施的強(qiáng)大實(shí)現(xiàn),比如密碼、權(quán)限以及安全的IPC機(jī)制。
- 一些安全技術(shù)的應(yīng)用,比如ASLR, NX, ProPolice, safe_iop, OpenBSD dlmalloc, OpenBSD calloc, 以及Linux mmap_min_addr,可以降低常見(jiàn)的內(nèi)存管理錯(cuò)誤風(fēng)險(xiǎn)。
- 文件加密系統(tǒng)可以保證設(shè)備在丟失后其中的數(shù)據(jù)不被盜取。
- 用戶權(quán)限授予可以限制訪問(wèn)系統(tǒng)特性以及用戶數(shù)據(jù)。
- Android定義的權(quán)限可以控制程序的數(shù)據(jù)只能在程序的控制范圍之內(nèi)。
本文中所提及的Android安全策略對(duì)于日常開(kāi)發(fā)非常重要,應(yīng)養(yǎng)成良好的編碼習(xí)慣。在日常的編碼行為中使用以下策略可以有效降低無(wú)意中造成的安全風(fēng)險(xiǎn)。
數(shù)據(jù)存儲(chǔ)
應(yīng)用程序常見(jiàn)的安全問(wèn)題就是它們的數(shù)據(jù)是否可被其它應(yīng)用程序訪問(wèn)到。Android有3種基本的數(shù)據(jù)存儲(chǔ)方式。
內(nèi)部存儲(chǔ)
默認(rèn)情況下,由APP自己創(chuàng)建的文件只能由APP本身訪問(wèn)。這種防護(hù)措施由Android框架實(shí)現(xiàn),也足以應(yīng)對(duì)大多數(shù)應(yīng)用的安全情況。
通常應(yīng)當(dāng)避免為IPC文件使用MODE_WORLD_WRITEABLE模式或MODE_WORLD_READABLE模式,因?yàn)檫@些模式?jīng)]有對(duì)數(shù)據(jù)的訪問(wèn)提供限制能力,也沒(méi)有在數(shù)據(jù)格式上做任何控制。如果需要在進(jìn)程間共享數(shù)據(jù),你應(yīng)當(dāng)考慮使用ContentProvider。ContentProvider對(duì)APP提供了數(shù)據(jù)讀寫(xiě)權(quán)限,也可以按照實(shí)際情況動(dòng)態(tài)的授予權(quán)限。
如果需要對(duì)一些較為敏感的數(shù)據(jù)提供額外的保護(hù),你可以使用密鑰對(duì)本地文件進(jìn)行加密。比如,可以將密鑰放入KeyStore,并以用戶密碼將其保護(hù)起來(lái)。不過(guò)這種方案也不是萬(wàn)能的:某些破解手段可以監(jiān)視用戶所輸入的密碼,不過(guò)這種方式可以對(duì)丟失的設(shè)備進(jìn)行保護(hù)。
外部存儲(chǔ)
在外部存儲(chǔ)器上創(chuàng)建的文件可被全局讀寫(xiě)。因?yàn)橥獠看鎯?chǔ)器可被用戶移除,也可以被任何的應(yīng)用程序修改,所以不應(yīng)當(dāng)在外部存儲(chǔ)器上存儲(chǔ)敏感的用戶數(shù)據(jù)。
正因?yàn)榭赡艽嬖诓豢尚刨Y源,所以從外部存儲(chǔ)器中讀取數(shù)據(jù)時(shí)應(yīng)當(dāng)執(zhí)行輸入驗(yàn)證。我們強(qiáng)烈的建議不要在外部存儲(chǔ)器上存儲(chǔ)用于動(dòng)態(tài)加載的可執(zhí)行文件或者類文件。如果APP需要從外部存儲(chǔ)器上接收可執(zhí)行文件,那么這些文件應(yīng)當(dāng)是被簽過(guò)名的,在加載之前也應(yīng)當(dāng)對(duì)這些簽名進(jìn)行校驗(yàn)。
內(nèi)容提供者
ContentProvider提供了一種結(jié)構(gòu)化的存儲(chǔ)機(jī)制,這種機(jī)制可以對(duì)所有的應(yīng)用程序形成一種約束。如果不打算使其它的應(yīng)用程序訪問(wèn)你的ContentProvider,那么只需在程序的清單文件中標(biāo)記ContentProvider的屬性android:exported=false即可。否則,設(shè)置android:exported=true便意味著其它應(yīng)用程序可以訪問(wèn)其中的數(shù)據(jù)。
在創(chuàng)建ContentProvider時(shí)默認(rèn)允許其它應(yīng)用程序可以訪問(wèn)其中的數(shù)據(jù),你可以對(duì)讀或者寫(xiě)進(jìn)行單一權(quán)限限制,也可以同時(shí)管理。
如果使用ContentProvider只是為了在自身的APP之間共享數(shù)據(jù),更加合理的方式是將android:protectionLevel屬性值設(shè)置為”signature”。Signature權(quán)限不需要用戶確認(rèn),所以這樣可以提供良好的用戶體驗(yàn),以及更多的控制力。
ContentProvider還可以通過(guò)android:grantUriPermissions屬性提供更細(xì)粒度的訪問(wèn)能力。訪問(wèn)者應(yīng)當(dāng)在Intent中使用FLAG_GRANT_READ_URI_PERMISSION標(biāo)志或FLAG_GRANT_WRITE_URI_PERMISSION標(biāo)志進(jìn)行訪問(wèn)。這些權(quán)限的范圍可被做更進(jìn)一步的限制。
當(dāng)訪問(wèn)ContentProvider時(shí),使用參數(shù)化方法比如query(), update(), 及delete()可以避免不可信來(lái)源的SQL注入。
不要對(duì)寫(xiě)入權(quán)限的安全擁有錯(cuò)誤的認(rèn)知。考慮一下,寫(xiě)入權(quán)限允許執(zhí)行SQL語(yǔ)句,這可能會(huì)使一些數(shù)據(jù)被確認(rèn)。比如,一名攻擊者可能會(huì)在通話記錄中查找一個(gè)指定的電話號(hào)碼是否存在,如果這條數(shù)據(jù)存在,那么攻擊者只需進(jìn)行修改便可得知結(jié)果。如果ContentProvider的數(shù)據(jù)結(jié)構(gòu)可被猜測(cè)出,那么寫(xiě)入權(quán)限就相當(dāng)于也同時(shí)提供了讀取權(quán)限。
使用權(quán)限
因?yàn)锳ndroid每個(gè)應(yīng)用都處于沙箱之內(nèi),所以如果需要共享資源與數(shù)據(jù)的話,應(yīng)用必須顯式的聲明自有權(quán)限。
請(qǐng)求權(quán)限
我們推薦應(yīng)用程序所需的權(quán)限越少越好。這樣可以降低權(quán)限濫用的風(fēng)險(xiǎn),也更易讓用戶接受,也可以減少黑客的攻擊入口。通常情況下,如果某個(gè)權(quán)限不是必要的,那就不要去請(qǐng)求它。
如果應(yīng)用程序可以做到不需要任何權(quán)限,那么這是最完美的。比如,如果需要通過(guò)訪問(wèn)設(shè)備信息的方式來(lái)創(chuàng)建唯一標(biāo)識(shí)符的話,我們更推薦GUID。又比如,相比于將數(shù)據(jù)存儲(chǔ)于外部存儲(chǔ)器,我們更推薦內(nèi)部存儲(chǔ)器。
另外在請(qǐng)求權(quán)限時(shí),可以使用< permissions>來(lái)保護(hù)IPC。IPC對(duì)于安全特別敏感、薄弱,并且它會(huì)被暴露給其它應(yīng)用程序,比如ContentProvider。 除了可能需要用戶確認(rèn)的權(quán)限之外,我們更推薦使用訪問(wèn)控制,因?yàn)檫@些權(quán)限可能會(huì)使用戶感到困惑、不解。比如,可以考慮對(duì)個(gè)人開(kāi)發(fā)者的應(yīng)用程序使用”signature“的IPC權(quán)限保護(hù)等級(jí)。
不要泄露受保護(hù)的權(quán)限數(shù)據(jù)。這種情況僅會(huì)發(fā)生在通過(guò)IPC共享數(shù)據(jù)時(shí):因?yàn)樗鼡碛刑厥獾臋?quán)限,并且對(duì)于任何的IPC接口的客戶端也沒(méi)有要求出示該權(quán)限。
More details on the potential impacts, and frequency of this type of problem is provided in this research paper published at USENIX:http://www.cs.berkeley.edu/~afelt/felt_usenixsec2011.pdf
創(chuàng)建權(quán)限
通常情況下應(yīng)當(dāng)盡量少的使用權(quán)限,少用權(quán)限就意味著更安全。創(chuàng)建權(quán)限這種事情對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)是用不到的,因?yàn)橄到y(tǒng)定義的權(quán)限足以涵蓋所有情況,這些權(quán)限會(huì)提供訪問(wèn)檢查。
如果必須創(chuàng)建權(quán)限,考慮是否可以使用”signature”保護(hù)等級(jí)完成你的所需任務(wù)。”signature”會(huì)將自身完全暴露給用戶,只允許具有相同簽名的應(yīng)用程序訪問(wèn)。
如果要?jiǎng)?chuàng)建”dangerous”保護(hù)等級(jí)的權(quán)限,那么有些東西需要考慮在內(nèi):
- 權(quán)限必須提供一段簡(jiǎn)短的描述該權(quán)限安全的字符串。
- 描述權(quán)限的字符串必須提供不同地區(qū)的語(yǔ)言。
- 如果權(quán)限的描述含糊不清或者用戶認(rèn)為這會(huì)為其帶來(lái)風(fēng)險(xiǎn),那么用戶可能會(huì)選擇不安裝應(yīng)用。
- 如果權(quán)限的生成器沒(méi)有安裝的話,應(yīng)用程序可能會(huì)請(qǐng)求權(quán)限。
上面的每一條對(duì)于作為程序員的你都是一項(xiàng)重要的非技術(shù)性挑戰(zhàn),這樣做可能會(huì)使用戶感到困惑,這就是為什么我們不鼓勵(lì)使用”dangerous”權(quán)限等級(jí)的原因。
網(wǎng)絡(luò)安全
網(wǎng)絡(luò)傳輸本身就存在安全風(fēng)險(xiǎn),因?yàn)樗鼤?huì)包括用戶的隱私數(shù)據(jù)。人們?cè)絹?lái)越關(guān)心移動(dòng)設(shè)備的隱私問(wèn)題,尤其是執(zhí)行網(wǎng)絡(luò)傳輸時(shí),所以APP需要至始至終以最佳的安全方案保護(hù)用戶的數(shù)據(jù)安全。
使用IP網(wǎng)絡(luò)
Android所處的網(wǎng)絡(luò)環(huán)境與其它的Linux系統(tǒng)有著很大的不同。主要考慮的就是選用適用于敏感數(shù)據(jù)傳輸?shù)膮f(xié)議。比如HttpsURLConnection用于安全的WEB通信。我們推薦在支持HTTPS,因?yàn)橐苿?dòng)設(shè)備會(huì)頻繁的連接到不可信網(wǎng)絡(luò),比如公共的Wi-Fi熱點(diǎn)。
經(jīng)認(rèn)證,Socket等級(jí)的加密通訊可以使用SSLSocket類簡(jiǎn)單實(shí)現(xiàn)。鑒于Android設(shè)備會(huì)頻繁的連接到不安全的無(wú)線網(wǎng)絡(luò),所以我們強(qiáng)力的建議對(duì)所有的應(yīng)用程序都使用安全的網(wǎng)絡(luò)實(shí)現(xiàn)。
我們也見(jiàn)過(guò)一些應(yīng)用在處理敏感的IPC上使用了localhost網(wǎng)絡(luò)端口。我們不鼓勵(lì)使用這種方式,因?yàn)檫@些接口能被其它應(yīng)用程序訪問(wèn)到,應(yīng)當(dāng)使用Android的IPC機(jī)制。
還有一個(gè)常見(jiàn)的問(wèn)題就是,根證書(shū)重復(fù)用于驗(yàn)證從HTTP或者其它網(wǎng)絡(luò)上下載的不可信數(shù)據(jù)。這也包括WebView以及HTTP請(qǐng)求響應(yīng)的輸入驗(yàn)證。
使用電話網(wǎng)絡(luò)
SMS(短消息服務(wù))協(xié)議主要用于個(gè)人對(duì)個(gè)人之間的通訊,它并不適用于APP的數(shù)據(jù)傳輸。由于SMS的限制,我們強(qiáng)烈的推薦使用Google Cloud Messaging(GCM)及IP網(wǎng)絡(luò)來(lái)傳輸服務(wù)器與設(shè)備之間的數(shù)據(jù)。
要注意,SMS既沒(méi)有對(duì)網(wǎng)絡(luò)和設(shè)備進(jìn)行加密也沒(méi)有對(duì)其進(jìn)行相關(guān)驗(yàn)證。尤其是,任何的SMS接收器應(yīng)當(dāng)考慮到會(huì)有一位惡意的用戶會(huì)發(fā)送SMS給你的應(yīng)用,不要相信沒(méi)有驗(yàn)證過(guò)的SMS數(shù)據(jù),并用它們來(lái)執(zhí)行一些敏感操作。還有,你應(yīng)當(dāng)意識(shí)到SMS可能會(huì)在網(wǎng)絡(luò)上被攔截并被篡改。在Android設(shè)備內(nèi),SMS消息是由廣播意圖傳送的,所以這些數(shù)據(jù)可以被擁有READ_SMS權(quán)限的應(yīng)用程序讀取到。
輸入驗(yàn)證
無(wú)論程序運(yùn)行在哪個(gè)平臺(tái)上,沒(méi)有執(zhí)行充分的輸入驗(yàn)證都是影響程序安全的主要原因之一。Android提供了平臺(tái)等級(jí)的安全策略,這可以降低應(yīng)用程序輸入驗(yàn)證問(wèn)題的暴露率,應(yīng)用程序應(yīng)當(dāng)盡可能的使用這些平臺(tái)特性。還應(yīng)該注意:安全性語(yǔ)言的選擇傾向于減少輸入驗(yàn)證問(wèn)題的可能性。
如果你在使用本地代碼,那么從文件中讀取的數(shù)據(jù)、從網(wǎng)絡(luò)上接收的數(shù)據(jù)或從IPC接收的數(shù)據(jù)都可能會(huì)引起安全問(wèn)題。最常見(jiàn)的問(wèn)題就是緩沖區(qū)溢出,使用釋放后的對(duì)象等等。Android提供了大量的相關(guān)技術(shù)手段比如ASLR(Address Space Layout Randomization)、DEP(Data Execution Prevention),這些技術(shù)手段可以降低這些錯(cuò)誤的出現(xiàn)頻率,但是它們不會(huì)解決根本的內(nèi)在問(wèn)題。你可以謹(jǐn)慎的處理指針或管理緩沖區(qū)來(lái)防止這些問(wèn)題的出現(xiàn)。
如果使用SQL數(shù)據(jù)庫(kù)或者ContentProvider進(jìn)行數(shù)據(jù)查詢,那么SQL注入可能是個(gè)問(wèn)題。避免這些問(wèn)題最好使用參數(shù)化的查詢方法。將權(quán)限降為只讀或只寫(xiě)可以降低SQL注入帶來(lái)的相關(guān)風(fēng)險(xiǎn)。
如果不能夠使用以上提及的安全建議,那么我們強(qiáng)烈推薦使用結(jié)構(gòu)良好的數(shù)據(jù)格式,并在使用時(shí)對(duì)這些數(shù)據(jù)格式進(jìn)行驗(yàn)證。
處理用戶數(shù)據(jù)
通常來(lái)說(shuō),對(duì)于用戶的數(shù)據(jù)安全最好的方法就是盡量少使用可以訪問(wèn)到敏感數(shù)據(jù)或者用戶數(shù)據(jù)的API。如果可以避免存儲(chǔ)或者傳輸這些信息,那么就不要傳輸這些數(shù)據(jù)。可考慮應(yīng)用程序是否能夠?qū)崿F(xiàn)這么一種邏輯:使用數(shù)據(jù)的哈希碼或者一種不可逆的數(shù)據(jù)形態(tài)。比如,程序可能會(huì)實(shí)現(xiàn)這么一種邏輯:將電子郵件地址的哈希碼作為一個(gè)關(guān)鍵的值,這樣可以避免使用原有的電子郵件地址,這可以降低暴露數(shù)據(jù)的機(jī)會(huì),也可以降低攻擊者入侵應(yīng)用程序的機(jī)會(huì)。
如果程序需要訪問(wèn)用戶的個(gè)人信息,比如密碼或者用戶名等等,要記住一些組件可能會(huì)要求你提供相關(guān)的隱私政策,來(lái)解釋這些數(shù)據(jù)的使用與存儲(chǔ)。所以接下來(lái)數(shù)據(jù)訪問(wèn)實(shí)踐可以簡(jiǎn)化遵循規(guī)則。
你還應(yīng)當(dāng)考慮應(yīng)用程序是否有無(wú)意中將用戶的個(gè)人數(shù)據(jù)暴露給了第三方。如果你不清楚這些第三方組件或服務(wù)為什么要使用用戶的信息,那么就不要提供給它們。通常降低個(gè)人信息的訪問(wèn)可以降低這塊的安全風(fēng)險(xiǎn)。
如果必須要訪問(wèn)敏感數(shù)據(jù),那么評(píng)估一下這些信息是否有必要傳輸?shù)椒?wù)器,或者是否這些操作只需在客戶端執(zhí)行就可以。考慮凡是涉及到用戶敏感數(shù)據(jù)的代碼都在客戶端執(zhí)行,這樣可以避免不必要的網(wǎng)絡(luò)傳輸和安全泄漏問(wèn)題。
還有,要確保沒(méi)有將用戶數(shù)據(jù)通過(guò)IPC、全局可讀寫(xiě)文件或者網(wǎng)絡(luò)Socket暴露給其它應(yīng)用程序。
如果需要GUID,可以創(chuàng)建一個(gè)大的唯一的數(shù)據(jù)將其保存下來(lái)。不要使用與電話有關(guān)的數(shù)字,比如電話號(hào)碼、IMEI,這些信息可能會(huì)與用戶信息有關(guān)。
寫(xiě)入設(shè)備日志時(shí)要當(dāng)心。在Android中,日志是共享資源,可被具有READ_LOGS權(quán)限的應(yīng)用讀取到。盡管日志數(shù)據(jù)是臨時(shí)的,但是不恰當(dāng)?shù)挠脩粜畔⑷罩究赡軙?huì)無(wú)意中將信息泄露給其它應(yīng)用程序。
WebView的使用
因?yàn)閃ebView會(huì)解析像HTML和JavaScript這樣的web內(nèi)容,所以不正確的使用會(huì)帶來(lái)常見(jiàn)的安全隱患。Android提供了大量機(jī)制來(lái)收縮這些潛在問(wèn)題的范圍,比如通過(guò)限制WebView的能力來(lái)達(dá)到最低的運(yùn)行需求。
如果程序沒(méi)有直接使用到WebView中的JavaScript,那么不要調(diào)用setJavaScriptEnabled()。一些示例代碼可能會(huì)使用該方法,所以如果不需要的話,在你的程序中關(guān)閉它。默認(rèn)情況下,WebView不會(huì)執(zhí)行JavaScript,所以不會(huì)發(fā)生跨站腳本攻擊。
使用addJavaScriptInterface()需要特別當(dāng)心,因?yàn)樗鼤?huì)允許JavaScript調(diào)用預(yù)留給Android原生應(yīng)用的方法。如果你使用它,要確認(rèn)所有的Web的相關(guān)內(nèi)容都是可信的。如果不可信的內(nèi)容允許進(jìn)入,那么不可信的 JavaScript 可能會(huì)調(diào)用App內(nèi)的相關(guān)方法。一般我們推薦在APK內(nèi)包含JavaScript代碼的時(shí)候使用addJavaScriptInterface()。
如果程序通過(guò)WebView訪問(wèn)敏感數(shù)據(jù),你可能需要使用clearCache()方法來(lái)刪除存儲(chǔ)在本地的所有文件。我們可以使用HTTP頭部的某些屬性比如no-cache來(lái)表示應(yīng)用程序不應(yīng)當(dāng)緩存某些特殊的內(nèi)容。
Android 4.4之前版本的webkit含有大量的安全問(wèn)題。如果App運(yùn)行在這些版本上,應(yīng)當(dāng)確認(rèn)WebView所渲染的內(nèi)容都是可信的。如果應(yīng)用必須渲染開(kāi)放的Web內(nèi)容,考慮實(shí)現(xiàn)一個(gè)獨(dú)有的渲染器,這樣可以及時(shí)更新相關(guān)的安全補(bǔ)丁。
管理證書(shū)
通常來(lái)說(shuō),我們不推薦頻繁的要求用戶憑證,推薦使用授權(quán)令牌。
用戶名及密碼通常不應(yīng)該存在本地。應(yīng)當(dāng)使用用戶輸入的用戶名及密碼進(jìn)行初始化驗(yàn)證,然后使用一個(gè)權(quán)限Token進(jìn)行通信。
如果一個(gè)賬戶需要被多個(gè)程序訪問(wèn),那么應(yīng)當(dāng)使用AccountManager。如果可能的話,使用AccountManager與服務(wù)進(jìn)行交互,絕不要將密碼存在設(shè)備上。
如果證書(shū)只是用作于你創(chuàng)建的應(yīng)用程序,那么可以使用checkSignature()方法進(jìn)行程序訪問(wèn)驗(yàn)證。如果只有一個(gè)程序使用了證書(shū),那么KeyStore可能更適合你。
使用密碼
除了數(shù)據(jù)隔離、文件系統(tǒng)加密、安全通信通道等保護(hù)手段之外,Android還提供了一系列通過(guò)算法加密的安全保護(hù)措施。
通常情況下,Android內(nèi)置的最高等級(jí)的安全實(shí)現(xiàn)已經(jīng)可以支持各種安全情況。如果需要從一個(gè)已知的位置接受一個(gè)文件,那么HTTPS URI已經(jīng)足夠。如果需要一條安全通道,考慮使用HttpsURLConnection或SSLSocket。
如果發(fā)現(xiàn)確實(shí)需要實(shí)現(xiàn)自己的安全協(xié)議,不建議自己實(shí)現(xiàn)加密算法。而應(yīng)當(dāng)使用已有的加密算法比如在Cipher中提供的AES加密算法或RSA加密算法。
使用安全隨機(jī)數(shù)生成器SecureRandom來(lái)初始化密鑰KeyGenerator。如果不使用由SecureRandom生成的密鑰的話,則會(huì)大大減弱加密算法的健壯性,也更容易遭受線下攻擊。
如果需要將密鑰存在本地以便后續(xù)使用,那么可以使用KeyStore類似的加密機(jī)制。
使用進(jìn)程間通信
一些App嘗試使用傳統(tǒng)的Linux技術(shù)比如網(wǎng)絡(luò)Socket和共享文件來(lái)實(shí)現(xiàn)IPC。我們對(duì)此推薦使用Android為IPC實(shí)現(xiàn)的系統(tǒng)功能,例如Intent,Binder,Messenger和BroadcastReceiver。Android的IPC機(jī)制允許驗(yàn)證連接到你IPC的程序的身份,并且可以對(duì)每個(gè)IPC機(jī)制設(shè)置安全策略。
許多安全元素通過(guò)IPC機(jī)制共享。如果你的IPC機(jī)制的目的不是為了供其他應(yīng)用程序使用,那么請(qǐng)將對(duì)應(yīng)元素的android:exported的屬性設(shè)置為false。這對(duì)于由相同UID的多進(jìn)程組成的應(yīng)用很有幫助,或者對(duì)后期再開(kāi)啟該功能也有一定的幫助。
如果IPC的目的是為了可被其他應(yīng)用訪問(wèn),你可以通過(guò)使用< permission>元素指定安全策略。如果IPC只是為了在持有相同key的兩個(gè)自有應(yīng)用中使用,那么android:protectionLevel=”signature”則更為適合。
使用Intent
Intent是異步IPC的首選機(jī)制。這取決于程序的需求,你可能會(huì)使用sendBroadcast(), sendOrderedBroadcast()或者顯式Intent來(lái)指定應(yīng)用程序組件。
要注意,由于有序廣播可以被接收方消耗掉,所以這些廣播可能不會(huì)被分發(fā)給所有的應(yīng)用程序。如果你發(fā)送了一個(gè)廣播,而該廣播必須被指定接收器接收的,那么必須使用顯式Intent,并且該Intent還需指明廣播接收器的名稱。
發(fā)送Intent的一方可以驗(yàn)證接收方是否允許非空的權(quán)限方法調(diào)用。只有含有該權(quán)限的應(yīng)用才會(huì)接收到該Inetnt。如果廣播中的Intent的數(shù)據(jù)是敏感的,那么應(yīng)當(dāng)考慮這里所使用的權(quán)限不會(huì)被非法的應(yīng)用程序攔截。在這種情況下,你應(yīng)當(dāng)考慮直接調(diào)用接收器,而不是使用廣播。
**Note:**Intent filters不應(yīng)當(dāng)被視作為一種安全特性:因?yàn)榻M件可能會(huì)由顯式的Intent調(diào)起。你應(yīng)當(dāng)在收到Intent的地方執(zhí)行輸入驗(yàn)證來(lái)確認(rèn)該Intent是否被格式化為適用于調(diào)用廣播接收器,服務(wù)或者Activity的格式。
使用服務(wù)
Service經(jīng)常被用作支持其他程序的功能。每個(gè)Service必須在它的清單文件中有相應(yīng)的聲明。
默認(rèn)情況下,Service不是開(kāi)放的,也不能夠被其它應(yīng)用程序調(diào)起。然而,如果在Service的聲明中添加了IntentFilter,那么默認(rèn)就會(huì)被暴露出去。最好的辦法就是顯式的聲明android:exported屬性為你需要的屬性。Service還可以由android:permission屬性保護(hù)。如果這么做了,那么其它的程序則需要在它們的清單文件中聲明對(duì)應(yīng)的權(quán)限才可以啟動(dòng)、停止或者綁定該服務(wù)。
Service還可以保護(hù)在其權(quán)限內(nèi)的IPC調(diào)用,在執(zhí)行這個(gè)調(diào)用的實(shí)現(xiàn)之前調(diào)用checkCallingPermission()進(jìn)行必要檢查。我們通常推薦使用在清單文件中聲明的權(quán)限,因?yàn)橛泻芏嗦┒磿?huì)被忽略。
使用Binder及Messenger接口
Binder、Messenger是遠(yuǎn)程過(guò)程調(diào)用的首要IPC機(jī)制。它們提供了一種定義良好的接口:可以進(jìn)行端對(duì)端相互認(rèn)證。
我們強(qiáng)烈推薦以不需要特定的權(quán)限檢查的方式設(shè)計(jì)接口。由于Binder、Messenger并不是在應(yīng)用的清單文件中聲明過(guò)的,因此不能對(duì)其采用特定權(quán)限。它們的權(quán)限通常來(lái)自于對(duì)應(yīng)的Service或Activity所聲明的權(quán)限。如果你創(chuàng)建了一個(gè)用于請(qǐng)求驗(yàn)證或者訪問(wèn)控制器的接口,那么這些控制器必須顯式的添加在Binder、Messenger的接口中。
如果創(chuàng)建了一個(gè)需要訪問(wèn)控制器的接口,使用checkCallingPermission()驗(yàn)證調(diào)用者是否含有所需的權(quán)限。這在訪問(wèn)服務(wù)的遠(yuǎn)端代理之前尤其重要,正如你的應(yīng)用的身份需要傳給其它接口一樣。如果調(diào)用一個(gè)由Service提供的接口,那么如果你沒(méi)有訪問(wèn)給定服務(wù)所需的權(quán)限,那么bindService()的調(diào)用可能會(huì)失敗。如果調(diào)用一個(gè)由自身APP提供的一個(gè)本地的接口,那么clearCallingIdentity()則可以滿足內(nèi)部安全檢查的需求。
有關(guān)更多執(zhí)行與服務(wù)有關(guān)的IPC的相關(guān)信息,請(qǐng)參見(jiàn)Bound Services。
使用廣播接收器
BroadcastReceiver用于處理由Intent發(fā)起的異步請(qǐng)求。
默認(rèn)情況下,接收器可以被任何應(yīng)用調(diào)起。如果你的廣播接收器的作用是給其它程序使用,那么可能需要對(duì)接收器采取一些安全措施:在清單文件中添加相應(yīng)的安全權(quán)限。這可以防止沒(méi)有正確權(quán)限的應(yīng)用程序發(fā)送Intent給廣播接收器。
動(dòng)態(tài)加載代碼
Dalvik是Android的運(yùn)行時(shí)虛擬機(jī)。雖然Dalvik專用于Android,但是其它虛擬機(jī)上的相關(guān)安全問(wèn)題也同樣適用于Android。一般不需要關(guān)心與虛擬機(jī)相關(guān)的安全問(wèn)題,因?yàn)锳ndroid的應(yīng)用程序運(yùn)行在安全的沙箱環(huán)境中,所以系統(tǒng)上的其它進(jìn)程訪問(wèn)不到程序的代碼或者私有數(shù)據(jù)。
如果你對(duì)更深的虛擬機(jī)安全課題感興趣,那么推薦熟悉一些現(xiàn)有的有關(guān)這一課題的相關(guān)文獻(xiàn)。其中最受歡迎的兩個(gè)資源如下:
- http://www.securingjava.com/toc.html
- https://www.owasp.org/index.php/Java_Security_Resources
這篇文檔主要關(guān)注于Android的特殊之處和與其它虛擬機(jī)環(huán)境有什么不同。對(duì)于對(duì)其它虛擬機(jī)很有經(jīng)驗(yàn)的開(kāi)發(fā)者來(lái)說(shuō),這里有兩個(gè)很主要的Android的不同之處:
- 一些虛擬機(jī),比如JVM或.net運(yùn)行時(shí),扮演了一個(gè)安全邊界的角色,從底層操作系統(tǒng)將代碼、功能隔離。然而在Android中Dalvik虛擬機(jī)并沒(méi)有這樣的功能——應(yīng)用程序沙箱實(shí)現(xiàn)與操作系統(tǒng)層面,所以Dalvik可以與應(yīng)用的本地代碼進(jìn)行交互,而沒(méi)有任何的安全限制。
- 由于移動(dòng)設(shè)備有限的存儲(chǔ)空間,一些開(kāi)發(fā)者可能需要通過(guò)模塊化構(gòu)建應(yīng)用程序,并使用動(dòng)態(tài)加載技術(shù)。如果這么做,那么則需要考慮在哪接收應(yīng)用的邏輯代碼?又應(yīng)當(dāng)將這些代碼存在哪?不要使用沒(méi)有經(jīng)過(guò)驗(yàn)證的代碼,比如從不安全的網(wǎng)絡(luò)資源上或者是外部存儲(chǔ)器中加載的代碼,因?yàn)檫@些代碼很有可能會(huì)被其它程序篡改。
本地代碼的安全
一般我們推薦使用Android SDK來(lái)進(jìn)行應(yīng)用程序開(kāi)發(fā),而不是使用本地代碼開(kāi)發(fā)。由本地代碼構(gòu)建的程序會(huì)更加復(fù)雜,也缺少了靈活性,也更容易產(chǎn)生像緩沖區(qū)溢出等常見(jiàn)的內(nèi)存泄露錯(cuò)誤。
因?yàn)锳ndroid建立于Linux kernel基礎(chǔ)之上,所以如果使用本地代碼的話,那么Linux開(kāi)發(fā)中所遇到的安全問(wèn)題也同樣適用于此。由于Linux安全相關(guān)超出了本文的范圍,所以這里提供了很受歡迎的“Linux和Unix如何安全編程”的相關(guān)資源,相關(guān)地址:http://www.dwheeler.com/secure-programs.
Android與其它大部分Linux環(huán)境最大的不同就在于程序沙箱。在Android中,所有的程序都運(yùn)行在程序沙箱中,也包括那些本地代碼。在最基本的層面上,對(duì)熟悉Linux的開(kāi)發(fā)者來(lái)說(shuō),不同之處就是Android的每個(gè)應(yīng)用程序都有一個(gè)唯一UID,也擁有少量的權(quán)限。如果要使用本地代碼開(kāi)發(fā)的話,那么應(yīng)當(dāng)對(duì)應(yīng)用的權(quán)限極為了解才對(duì)。
PS: 翻譯的相關(guān)源文件皆已開(kāi)源,開(kāi)源地址:https://code.csdn.net/u011064099/android-training-chinese-version/tree/master,歡迎fork、star。
總結(jié)
以上是生活随笔為你收集整理的Android官方开发文档Training系列课程中文版:Android的安全建议的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 笔记:猎头如何在一周之内“摸清”一个行业
- 下一篇: pytorch 和 tensorflow