Android 應用的安全總結
Android 作業系統內建了安全功能,可顯著降低應用出現安全問題的頻率及其造成的影響。系統經過精心設計,您在通常情況下只需使用預設的系統和檔案許可權即可打造自己的應用,而無需費心針對安全性作出艱難決策。
下面是一些可以幫助您打造安全應用的核心安全功能:
- Android 應用沙盒,可以將您的應用資料和程式碼執行與其他應用分隔開來。
- 應用框架,可以穩健實現常見的安全性功能,例如加密、許可權和安全 IPC。
- ASLR、NX、ProPolice、safe_iop、OpenBSD dlmalloc、OpenBSD calloc 和 Linux mmap_min_addr 等多項技術,可降低與常見記憶體管理錯誤相關的風險。
- 加密的檔案系統,啟用後可保護丟失或被盜裝置上的資料。
- 使用者授予的許可權,可用來限制對系統功能和使用者資料的使用。
- 應用定義的許可權,可針對各個應用分別控制應用資料。
不過,我們仍建議您熟悉一下本文件中所述的 Android 安全性最佳做法。遵循這些最佳做法,養成常規編碼習慣,就可以有效減少因疏忽而引發安全問題的機率,防止對使用者產生不利的影響。
儲存資料
對於 Android 應用,最常見的安全問題就是其他應用能否訪問使用者儲存在裝置上的資料。下面介紹了將資料儲存在裝置上的三種基本方法:
使用內部儲存空間
預設情況下,您在內部儲存空間中建立的檔案僅供您的應用訪問。這項保護措施由 Android 實現,而且這對於大多數應用來說足夠了。
一般情況下,建議您儘量避免將 MODE_WORLD_WRITEABLE或 MODE_WORLD_READABLE模式用於IPC檔案,因為在這兩種模式下,系統不提供針對特定應用限制資料訪問的功能,也不會對資料格式進行任何控制。如果您想與其他應用程序共享資料,不妨考慮使用ContentProvider,它可以為其他應用提供讀取和寫入許可權,還能針對各種具體情況授予動態許可權。
要為敏感資料提供額外的保護,您可以選擇使用該應用無法直接訪問的金鑰來對本地檔案進行加密。例如,您可以將金鑰儲存在 KeyStore 中,並使用未儲存在相應裝置上的使用者密碼加以保護。不過,如果攻擊者獲得超級使用者許可權,就可以在使用者輸入密碼時進行監控,資料也就失去了這層保護屏障;但是,這種方式可以保護丟失裝置上的資料,而無需進行檔案系統加密。
使用外部儲存裝置
在外部儲存裝置(例如 SD 卡)上建立的檔案不受任何讀取和寫入許可權的限制。對於外部儲存裝置中的內容,不僅使用者可以將其移除,而且任何應用都可以對其進行修改,因此最好不要使用外部儲存裝置來儲存敏感資訊。
就像處理來源不受信任的資料一樣,您應對外部儲存裝置中的資料執行輸入驗證。強烈建議您不要在動態載入前將可執行檔案或類檔案儲存在外部儲存裝置中。如果您的應用確實從外部儲存裝置中檢索可執行檔案,請在動態載入前對這些檔案執行簽名和加密驗證。
使用內容提供程式
ContentProvider提供結構化儲存機制,可以將內容限制為僅供自己的應用訪問,也可以將內容匯出以供其他應用訪問。如果您不打算向其他應用授予訪問您的ContentProvider 的許可權,請在應用清單中將其標記為android:exported=false
;要允許其他應用訪問儲存的資料,請將android:exported
屬性設定為"true"
。
在建立要匯出以供其他應用使用的ContentProvider
時,您可以在清單中指定允許讀取和寫入的單一許可權,也可以針對讀取和寫入操作分別指定許可權。我們建議您僅對需要完成相應任務的應用授予許可權。請注意,與其移除許可權而影響到現有使用者,不如以後要使用新功能時再新增許可權。
如果您要使用內容提供程式僅在自己的應用之間共享資料,最好將android:protectionLevel
屬性設定為"signature"
保護級別。簽名許可權不需要使用者確認,因此,這種方式不僅能提升使用者體驗,而且在相關應用使用相同的金鑰進行簽名來訪問資料時,還能更好地控制對內容提供程式資料的訪問。
內容提供程式還可以通過以下方式提供更細化的訪問許可權:宣告android:grantUriPermissions
屬性,並使用用來啟動元件的 Intent 物件中的FLAG_GRANT_READ_URI_PERMISSION
標記。使用<grant-uri-permission element>
還能進一步限制這些許可權的範圍。
訪問內容提供程式時,請使用引數化的查詢方法(例如query())
、update()
和delete()
),以免產生來源不受信任的 SQL 注入風險。請注意,如果以組合使用者資料的方式構建selection
引數,然後再將其提交至引數化方法,則使用引數化方法可能不夠安全。
請不要誤以為提供寫入許可權很安全。設想一下,寫入許可權允許使用 SQL 語句,這使得攻擊者可以通過使用各種WHERE
子句以及對相關結果進行解析來確認某些資料。例如,如果攻擊者想要探查通話記錄中是否存在某個特定電話號碼,只要該號碼已經存在,攻擊者就可以通過修改其中的一行來獲知。如果內容提供程式資料採用可預測的結構,那麼授予寫入許可權相當於同時提供了讀取和寫入許可權。
使用許可權
由於 Android 通過沙盒機制管理各個應用,因此應用必須以明確的方式共享資源和資料。應用會通過宣告自己需要的許可權來獲取基本沙盒未提供的額外功能(包括對相機等裝置功能的訪問許可權),從而實現這一點。
請求許可權
我們建議您儘量減少應用請求的許可權。如果不具備對敏感資料的訪問許可權,就能降低不慎誤用這類許可權的風險,並可提高使用者的採用率,同時讓您的應用不那麼容易受到攻擊者的攻擊。一般來說,如果您的應用無需某項許可權也能正常執行,就不要請求該許可權。
如果可以採用不需要任何許可權的方式設計應用,建議採用這種方式。例如,與其請求訪問裝置資訊的許可權以建立唯一識別符號,不如為您的應用建立一個ofollow,noindex">GUID (請參閱處理使用者資料 的相關部分)。或者,您也可以不將資料儲存在外部儲存裝置(需要請求許可權),而將其儲存在內部儲存空間。
除了請求許可權之外,您的應用也可以使用
<permissions>
來保護對安全性要求較高且會被其他應用訪問的 IPC,例如ContentProvider
。一般而言,我們建議您儘量使用訪問許可權控制,而不使用需要使用者確認的許可權,因為許可權管理對使用者來說可能比較複雜。例如,對於同一開發者提供的不同應用之間的 IPC 通訊,不妨使用"signature" 保護級別
。
請勿洩露受許可權保護的資料。當您的應用通過 IPC 傳輸資料時可能會出現洩漏,不過,只有您的應用擁有特定許可權時,才可能發生資料洩漏。應用 IPC 介面的客戶端可能沒有相同的資料訪問許可權。要詳細瞭解潛在影響以及這類問題發生的頻率,請參閱在 USENIX 上釋出的這篇研究論文 。
建立許可權
一般來說,您應在滿足安全性要求的前提下儘可能少定義許可權。對於大多數應用來說,它們很少會建立新許可權,因為系統定義的許可權 就能滿足大部分的需求。請視需要使用現有許可權執行訪問許可權檢查。
如果必須建立新許可權,請儘量考慮建立"signature" 保護級別 的許可權。“簽名”級別許可權的內容對使用者完全透明開放,而且只有由執行許可權檢查的應用的開發者簽名的應用才可訪問這些內容。
如果您建立了"dangerous" 保護級別 的許可權,則事情就會更加複雜,您需要注意:
- 該許可權必須包含一個字串,向用戶清楚明確地說明他們需要做出的安全決策。
- 該許可權的字串必須翻譯成多種不同語言。
- 使用者可能會因為許可權含糊不清或存在風險而選擇不安裝應用。
- 應用可能會在許可權建立程式尚未安裝的情況下請求許可權。
這些事情會給開發者帶來巨大的非技術性挑戰,也讓使用者感到困惑,因此我們不鼓勵使用 "dangerous" 許可權級別。
使用網路
網路交易涉及傳輸對使用者而言可能比較私密的資料,因此本質上就存在安全風險。使用者開始逐漸意識到移動裝置存在的隱私洩漏問題,尤其是在通過裝置進行網路交易時。因此,請務必對您的應用採取各種最佳做法,以始終確保使用者的資料安全。
使用 IP 網路
Android 網路執行機制與其他 Linux 環境差別不大,關鍵是確保對敏感資料使用合適的協議,如使用HttpsURLConnection
來保證網路流量安全。我們建議您在伺服器支援 HTTPS 的情況下一律使用 HTTPS(而非 HTTP),因為移動裝置經常會連線到不安全的網路(如公共 WLAN 熱點)。
您可以使用SSLSocket
類輕鬆實現經過身份驗證和加密的套接字層通訊。考慮到 Android 裝置會頻繁使用 WLAN 連線到不安全的無線網路,我們強烈建議所有通過網路通訊的應用使用安全的網路。
我們發現有些應用使用localhost
網路埠處理敏感的 IPC。我們不建議採用這種方法,因為裝置上的其他應用也可以訪問這些介面。相反,您應該使用可通過Service
等進行身份驗證的 Android IPC 機制。(繫結到 INADDR_ANY 比使用回送功能還要糟糕,因為這樣一來,您的應用可能會收到任何位置發來的請求。)
此外,還有一個需要再三強調的常見問題就是,切勿相信通過 HTTP 或其他非安全協議下載的資料,包括WebView
中的輸入驗證以及對通過 HTTP 發出的 intent 的任何響應。
使用電話網路
簡訊協議主要是為使用者間通訊設計的,並不適合要傳輸資料的應用。考慮到簡訊的侷限性,因此,想從網路伺服器向用戶裝置上安裝的應用傳送資料訊息時,我們強烈建議您使用Google 雲訊息傳遞(GCM) 和 IP 網路。
請注意,簡訊在網路上和裝置上均未經過加密,也沒有經過嚴格的身份驗證。而且,簡訊的所有接收者都應明白,您的應用收到的簡訊可能來自惡意使用者。因此,切勿使用未經身份驗證的簡訊資料執行敏感命令。還需要注意的是,簡訊可能包含欺騙性內容,也有可能在網路上傳輸時被攔截。在 Android 裝置上,簡訊會以廣播 intent 的形式傳輸,因此可能會被其他擁有READ_SMS
許可權的應用讀取或捕獲。
執行輸入驗證
無論應用是在哪種平臺上執行,輸入驗證功能不完善都是影響應用的最常見安全問題。Android 為此提供了平臺級對策,可降低應用出現輸入驗證問題的可能性。如果可行,請儘量使用這些功能。另請注意,選擇型別安全的語言通常也有助於降低出現輸入驗證問題的可能性。
如果使用原生程式碼,那麼系統從檔案讀取、通過網路接收或從 IPC 接收的任何資料都有可能會引發安全問題。最常見的問題包括緩衝區溢位 、釋放後重用 和差一錯誤 。Android 為此提供了多項技術,例如 ASLR和 DEP,可以降低這些錯誤被利用的可能性,但無法解決根本問題。因此,請謹慎管理指標和緩衝區,預防這些漏洞造成破壞。
使用基於字串的動態語言(如 JavaScript 和 SQL)也可能因為轉義字元和指令碼注入 而出現輸入驗證問題。
如果使用提交到 SQL 資料庫或內容提供程式的查詢中的資料,也可能出現 SQL 注入問題。最好的預防措施是使用引數化查詢(請參閱上文內容提供程式 部分的相關內容)。將許可權限制為只讀或只寫,也可以降低 SQL 注入引發破壞的可能性。
如果您無法使用上述安全功能,我們強烈建議您使用結構合理的資料格式,並驗證資料是否符合預期的格式。雖然將字元列入黑名單或替換字元是一種有效的策略,但這些技術在實際操作中很容易出錯,因此應儘量避免使用。
處理使用者資料
通常情況下,確保使用者資料安全的最佳做法是儘量避免使用會訪問使用者敏感資料或個人資料的 API。如果您擁有使用者資料的訪問許可權,並且能夠避免儲存或傳輸這些資訊,那麼就不要儲存或傳輸這些資料。最後,請評估您的應用邏輯能否使用經過雜湊演算法處理或不可逆的資料格式進行實現。例如,您的應用可能會使用電子郵件地址的雜湊值作為主要金鑰,以避免傳輸或儲存電子郵件地址。這樣可降低在無意之中洩露資料的可能性,還可以降低攻擊者嘗試利用您的應用搞破壞的可能性。
請注意,如果您的應用會訪問密碼或使用者名稱等個人資訊,部分司法轄區可能會要求您提供隱私權政策,以說明您如何使用或儲存這類資料。因此,遵循安全最佳做法(即儘可能減少對使用者資料的訪問)也有助於簡化合規工作。
此外,您還應考慮自己的應用是否會在無意之中將個人資訊洩露給其他方,如廣告使用的第三方元件或應用使用的第三方服務。如果不知道某個元件或服務為什麼需要個人資訊,就不要提供個人資訊。通常,減少您的應用對個人資訊的訪問,可以降低引發這方面問題的可能性。
如果必須訪問敏感資料,請判斷這些資訊是必須傳輸至伺服器,還是可以在客戶端上執行相應操作。建議您在客戶端上執行所有需要使用敏感資料的程式碼,以避免傳輸使用者資料。
此外,請務必不要使用許可權過於寬鬆的 IPC、完全沒有寫入限制的檔案或網路套接字,避免在無意之中將使用者資料洩露給裝置上的其他應用。這屬於一種造成受許可權保護的資料遭洩露的特殊情況,我們已在請求許可權 部分討論過。
如果需要GUI ,請建立一個較長的具有唯一性的編號並加以儲存。請勿使用可能與個人資訊關聯的電話識別符號,如電話號碼或 IMEI。有關此主題的詳情,請參閱Android 開發者部落格 。
向裝置上的日誌寫入內容時,請務必謹慎小心。在 Android 中,日誌是共享資源,擁有READ_LOGS
許可權的所有應用均可訪問。即使電話日誌資料是臨時資料並會在重新啟動時清空,不當記錄使用者資訊也可能在無意之中將使用者資料洩露給其他應用。
使用 WebView
由於WebView
使用的網路內容可能包含 HTML 和 JavaScript,當的使用可能引入常見的網路安全問題,例如跨站指令碼攻擊
(JavaScript 注入)。Android 內建了多種機制,可將WebView
的功能限制為您應用所需的最低功能,以縮小這些潛在問題的影響範圍。
如果您的應用不直接使用WebView
中的 JavaScript,請勿
呼叫setJavaScriptEnabled()
。部分示例程式碼會使用這種方法,不過您可能需要在實際應用時根據具體情況進行調整。因此,如果不需要使用這種呼叫方法,請將其移除。預設情況下,WebView
不會執行 JavaScript,因此不可能出現跨站指令碼攻擊這樣的安全問題。
addJavaScriptInterface()
允許 JavaScript 呼叫正常情況下是為 Android 應用預留的操作,因此在使用時請格外小心。如果要使用,請僅將addJavaScriptInterface()
用於所有輸入內容都可信的網頁。如果您接受不受信任的輸入內容,那麼不受信任的 JavaScript 可能會呼叫您應用中的 Android 方法。一般情況下,我們建議您僅將addJavaScriptInterface()
用於應用 APK 內含的 JavaScript。
如果您的應用通過WebView
訪問敏感資料,您可能需要使用clearCache()
方法來刪除本地儲存的所有檔案。您也可以使用伺服器端標頭(例如no-cache
)來指示應用不應快取特定內容。
在 Android 4.4(API 級別 19)之前平臺上執行的裝置使用的webkit
版本存在多個安全問題。如果您的應用在這些裝置上執行,解決方法是確認WebView
物件只顯示值得信任的內容。還應使用可更新的安全Provider
物件確保您的應用在 SSL 中不會暴露給潛在的漏洞,如更新您的安全提供程式以防範 SSL 攻擊
中所述。如果您的應用必須從開放網路渲染內容,請考慮提供您自己的渲染程式,以便使用最新的安全補丁程式保持其處於最新狀態。
處理憑據
一般情況下,我們建議您儘量降低要求使用者憑據的頻率;這樣會讓釣魚攻擊顯得比較可疑,從而能夠降低其成功率。作為替代方法,您可以使用授權令牌並根據需要重新整理。
請儘量避免將使用者名稱和密碼儲存在裝置上。您可以使用使用者提供的使用者名稱和密碼進行初始身份驗證,然後使用針對特定服務的短時效授權令牌。
可供多個應用訪問的服務應使用AccountManager
進行訪問。如果可行,請使用AccountManager
類來呼叫基於雲的服務;此外,請勿將密碼儲存在裝置上。
使用AccountManager
檢索Account
後,請先確認CREATOR
再傳送憑據,以免無意中將憑據傳送給錯誤的應用。
如果憑據僅供您建立的應用使用,那麼您可以使用checkSignature()
驗證訪問AccountManager
的應用。另外,如果只有一個應用使用該憑據,那麼您可以使用KeyStore
儲存憑據。
使用加密
Android 不僅提供資料隔離機制、支援完整檔案系統加密並提供安全通訊通道,還提供大量使用加密來保護資料的演算法。
一般情況下,請嘗試根據您的具體情況使用已經實現的最高級別的框架。如果您需要從某個已知位置安全地檢索檔案,使用簡單的 HTTPS URI 即可滿足需要,無需具備加密知識。如果您需要一個安全通道,不妨考慮使用HttpsURLConnection
或SSLSocket
,而無需自行編寫協議。
如果您需要實現自己的協議,我們強烈建議您不要
實現自己的加密演算法。請使用現有加密演算法,例如Cipher
類中提供的 AES 或 RSA 實現中的演算法。
使用安全隨機數生成器SecureRandom
初始化任意加密金鑰KeyGenerator
。如果使用的金鑰不是安全隨機數生成器生成的,那麼會顯著降低演算法的強度,容易導致出現離線攻擊。
如果您需要儲存金鑰以供重複使用,請使用KeyStore
等可以長期儲存和檢索加密金鑰的機制。
使用程序間通訊
部分應用會嘗試使用傳統 Linux 技術(如網路套接字和共享檔案)來實現 IPC。強烈建議您改為使用 Android 針對 IPC 提供的系統功能,例如使用Service
的Intent
、Binder或
Messenger,以及
BroadcastReceiver`。Android IPC 機制讓您驗證連線至 IPC 的應用的身份,併為每種 IPC 機制設定安全策略。
許多安全元素在各種 IPC 機制之間是共享的。如果您的 IPC 機制並不打算讓其他應用使用,請在該元件的清單元素(例如<service>
元素)中將android:exported
屬性設定為"false"
。對於同一 UID 中包含多項程序的應用,這種做法非常有用;當您在以後的開發過程中決定不以 IPC 的形式提供功能但又不想重新編寫程式碼時,這樣做也會有所助益。
如果您的 IPC 預期供其他應用訪問,您可以使用<permission>
元素應用安全策略。如果 IPC 是在您自己的不同應用(以同一金鑰登入)之間使用,建議您在android:protectionLevel
中使用"signature"
級別許可權。
使用 Intent
Intent 是 Android 中非同步 IPC 的首選機制。根據您的應用要求,您可能會對特定的應用元件使用sendBroadcast()
、sendOrderedBroadcast()
或顯式 intent。
請注意,排序後的廣播可能會被接收者“佔用”,因此它們可能不會傳遞到所有應用。如果您要傳送必須傳遞到特定接收者的 intent,那麼必須使用以 nameintent 宣告接收者的顯式 intent。
Intent 的傳送器會驗證接收者是否有權通過方法呼叫來指定非空許可權。只有具有該許可權的應用才會收到 intent。如果廣播 intent 中的資料屬於敏感資料,則不妨考慮應用相應許可權,以確保惡意應用在沒有相應許可權的情況下無法註冊以接收這些訊息。在這些情況下,您還可以考慮直接呼叫接收器,而不是發起廣播。
注:請勿將 intent 過濾條件視為安全功能 - 元件可通過顯式 intent 呼叫,但不一定擁有符合 intent 過濾條件的資料。您需要在 intent 接收器中執行輸入驗證,以確認 intent 的格式正確無誤,可用於呼叫的接收器、服務或 Activity。
使用服務
Service
通常用於提供其他應用要使用的功能。每個服務類在其清單檔案中都必須有相應的<service>
宣告。
預設情況下,服務不會被匯出,而且無法由任何其他應用呼叫。不過,如果您將任何 intent 過濾條件新增到服務宣告中,那麼預設就會匯出該服務。最好是明確宣告android:exported
屬性,以確保其行為符合您的需要。您也可以使用android:permission
屬性來保護服務。這樣一來,其他應用只有在自己的清單中宣告相應的<uses-permission>
元素,才能啟動、停止或繫結到服務。
服務可以先呼叫checkCallingPermission()
,然後再實現該呼叫,從而保護針對該服務、擁有相應許可權的各個 IPC 呼叫。通常情況下,我們建議您在清單中使用宣告式許可權,因為這些許可權不容易被忽略。
使用 Binder 和 Messenger 介面
使用Binder
或Messenger
是 Android 中 RPC 式 IPC 的首選機制。它們提供了定義完善的介面,可讓端點互相進行身份驗證(如果需要)。
我們強烈建議您在設計介面時,採取無需針對介面進行特定許可權檢查的方式。應用清單中並未宣告Binde
和Messenger
物件,因此您無法向這些物件直接應用宣告式許可權。一般情況下,如果您在Service
或Activity
中實現了這些物件,那麼它們會繼承 Service 或 Activity 的應用清單中宣告的許可權。如果您要建立一個需要身份驗證和/或訪問控制元件的介面,則這些控制元件必須以程式碼的形式明確新增到Binde
或Messenger
介面中。
如果您提供的介面確實需要訪問控制元件,請使用checkCallingPermission()
驗證呼叫者是否具備所需許可權。在代表呼叫者訪問服務前,請務必執行此操作,因為您應用的身份會傳遞到其他介面。如果您呼叫的是Service
提供的介面,在沒有訪問指定服務的許可權的情況下,bindService
呼叫可能會失敗。如果您呼叫的是自己的應用提供的本地介面,不妨使用clearCallingIdentity()
來確保滿足內部安全檢查的要求。
使用廣播接收器
BroadcastReceiver
會處理Intent
發起的非同步請求。
預設情況下,接收器會被匯出,而且可以由任何其他應用呼叫。如果您的BroadcastReceiver
預期供其他應用使用,您可能需要使用應用清單中的<receiver>
元素向接收器應用安全許可權。這樣可防止沒有相應許可權的應用向BroadcastReceiver
傳送 intent。
動態載入程式碼
我們強烈建議您不要從應用 APK 外部載入程式碼。這樣做不僅會明顯加大應用因程式碼注入或程式碼篡改產生問題的可能性,還會增加版本管理和應用測試的難度。這最終會導致無法驗證應用的行為,因此,某些環境中可能會禁止採用此做法。
如果您的應用會動態載入程式碼,您務必謹記,執行動態載入的程式碼需要擁有與應用 APK 相同的安全許可權。使用者是因為您才決定安裝您的應用的,因此他們希望您提供的是在您的應用內執行的程式碼,包括動態載入的程式碼。
與動態載入程式碼相關的主要安全風險與這樣的程式碼需要來自可驗證的來源有關。如果這些模組已直接納入您的 APK 中,那麼其他應用就無法對其進行修改;無論程式碼是原生庫程式碼還是使用DexClassLoader
載入的類,均是如此。我們見過很多應用嘗試從不安全的位置(例如,通過未加密的協議從網路上進行下載)或任何人都可寫入內容的位置(如外部儲存裝置)載入程式碼的例子;對於前一種位置,網路上的使用者將可以修改正在傳輸的內容,對於後一種位置,使用者裝置上的其他應用將可以修改裝置上的內容。
虛擬機器中的安全性
Dalvik 是 Android 的執行時虛擬機器 (VM)。雖然 Dalvik 是專為 Android 而設計的,但是其他虛擬機器中遇到的很多安全程式碼問題在 Android 中也會出現。一般情況下,您無需擔心有關虛擬機器的安全問題。您的應用在安全的沙盒環境中執行,因此係統中的其他程序無法訪問您的程式碼或隱私資料。
如果希望深入瞭解虛擬機器安全性,建議您研讀有關這方面的一些現有文獻。下面是兩種比較受歡迎的資源:
本文將重點說明 Android 特有或不同於其他虛擬機器環境的方面。對於熟悉在其他環境中進行虛擬機器程式設計的開發者,需要注意為 Android 編寫應用的兩大不同之處:
- 有些虛擬機器(例如 JVM 或 .net 執行時)會充當安全邊界,將程式碼與基本作業系統功能分隔開來。在 Android 上,Dalvik 虛擬機器不起安全邊界的作用 — 應用沙盒是在作業系統級別進行實現的,因此 Dalvik 可與同一應用中的原生程式碼進行互操作,沒有安全限制。
- 鑑於移動裝置上的儲存空間有限,開發者一般希望開發模組化應用並使用動態類載入。這樣做時,請同時考慮您檢索應用邏輯的來源以及您在本地儲存應用邏輯的位置。請勿使用從未經驗證的來源(如不安全的網路來源或外部儲存裝置)載入的動態類,因為這類程式碼可能遭到篡改,從而執行某些惡意操作。
原生程式碼中的安全性
一般情況下,我們鼓勵開發者使用 Android SDK 來開發應用,而不要使用Android NDK 編寫原生程式碼。通過原生程式碼開發的應用比較複雜、可移植性較差,並且很可能會出現常見的記憶體損壞錯誤,如緩衝區溢位。
Android 使用 Linux 核心構建而成。如果您要使用原生程式碼,熟悉一下 Linux 開發安全最佳做法會非常有用。本文中沒有介紹 Linux 安全做法,不過您可以查閱非常受歡迎的《Secure Programming for Linux and Unix HOWTO》,網址為http://www.dwheeler.com/secure-programs 。
Android 與大多數 Linux 環境之間的一個重要區別在於應用沙盒。在 Android 上,所有應用都在應用沙盒中執行,包括那些採用原生程式碼編寫的應用。對於熟悉 Linux 的開發者而言,其本質完全可以彙總成一句話:每個應用都被賦予唯一的 UID和非常有限的許可權。這樣就很好理解了。此外,即使您使用的是原生程式碼,也最好熟悉各種應用許可權。