安全性提示

Android 內建安全性功能,可大幅降低應用程式安全性問題的頻率和影響。這個系統經過特殊設計,通常可讓您使用預設的系統和檔案權限來建構應用程式,省去複雜的安全性決策。

下列核心安全性功能可協助您建構安全的應用程式:

  • Android 應用程式沙箱,可將您的應用程式資料和程式碼執行與其他應用程式隔離。
  • 應用程式架構,提供完善的常見安全性功能實作,例如密碼編譯、權限和安全的處理序間通訊 (IPC)。
  • 採用位址空間配置隨機化 (ASLR)no-執行 (NX)、ProPolice、safe_iopOpenBSD dlmalloccalloc 和 Linux mmap_min_addr 等技術,以減輕常見記憶體管理錯誤相關的風險。
  • 加密的檔案系統,可啟用用於保護遺失或遭竊裝置中的資料。
  • 由使用者授予的權限,可限制系統功能和使用者資料的存取權。
  • 根據應用程式設定的權限,針對個別應用程式管理其資料。

請務必熟悉本頁的 Android 安全性最佳做法。遵循這些程式設計一般程式設計習慣,就能避免意外產生會對使用者造成負面影響的安全性問題。

資料儲存

對於 Android 應用程式,最常見的安全考量就是其他應用程式是否可存取您儲存在裝置上的資料。在裝置上儲存資料的基本方式有三種:

  • 內部儲存空間
  • 外部儲存空間
  • 內容供應器
以下各節說明與各種方法相關的安全性問題。

內部儲存空間

根據預設,您在內部儲存空間建立的檔案只有您的應用程式可以存取。Android 導入了這項保護機制,足以適用於大多數應用程式。

避免使用已淘汰的 IPC 檔案 MODE_WORLD_WRITEABLEMODE_WORLD_READABLE 模式。無法限制特定應用程式的資料存取權,也不提供任何資料格式的控制權。如果您想與其他應用程式程序共用資料,請考慮改用內容供應器,以便為其他應用程式提供讀取和寫入權限,並依照個別情況授予動態權限。

如要為機密資料提供額外的保護,您可以使用 Security 程式庫加密本機檔案。這項措施可在不檔案系統加密的情況下為遺失的裝置提供保護。

外部儲存空間

外部儲存空間 (例如 SD 卡) 建立的檔案是全域通用的可讀取及寫入。由於外部儲存空間可由使用者移除,也能由任何應用程式修改,因此請僅使用外部儲存空間儲存非機密資訊。

如要以更安全的方式讀取及寫入外部儲存空間中的檔案,請考慮使用提供 EncryptedFile 類別的 Security 程式庫。

處理外部儲存空間的資料時,如同處理任何不受信任的來源中的資料一樣,請執行輸入驗證。在動態載入之前,請勿將執行檔或類別檔案儲存在外部儲存空間。如果應用程式會從外部儲存空間擷取執行檔,請務必在動態載入之前,確認檔案經過簽署及加密驗證。

內容供應器

內容供應器提供結構化的儲存機制,可限制僅供您的應用程式存取,或匯出以供其他應用程式存取。如果您不想將 ContentProvider 存取權授予其他應用程式,請在應用程式資訊清單中將其標示為 android:exported=false。否則,請將 android:exported 屬性設為 true,讓其他應用程式存取儲存的資料。

建立匯出供其他應用程式使用的 ContentProvider 時,您可以指定單一的讀取和寫入權限 ,或是指定不同的讀取和寫入權限。請僅授予完成手邊工作所需的權限。請記住,比起立即移除權限並影響現有使用者,日後再新增權限來公開新功能,通常比較容易。

如果您使用內容供應器,但只有自家應用程式共用資料,建議使用 android:protectionLevel 屬性設為 signature 防護。簽章權限不需使用者確認,因此如果存取資料的應用程式使用相同金鑰簽署,使用者就能提供更優質的使用者體驗,並更能控管內容供應器資料的存取權。

內容供應器也可透過宣告 android:grantUriPermissions 屬性,並在啟動元件的 Intent 物件中使用 FLAG_GRANT_READ_URI_PERMISSIONFLAG_GRANT_WRITE_URI_PERMISSION 旗標,提供更精細的存取權。這些權限的範圍可以進一步受到 <grant-uri-permission> 元素限制。

存取內容供應器時,請使用參數化查詢方法 (例如 query()update()delete()),避免從不受信任的來源插入 SQL 的潛在內容。請注意,如果要建立 selection 引數的方式是串連使用者資料,再將使用者資料提交至方法,那麼使用參數化方法並不足夠。

請不要誤認寫入權限的安全性,寫入權限可讓 SQL 陳述式使用廣告素材 WHERE 子句並剖析結果來確認部分資料。舉例來說,攻擊者可能只有在該電話號碼存在的情況下,才能修改資料列,藉此探測通話記錄中是否存在特定電話號碼。如果內容供應器資料具有可預測的結構,則寫入權限可能就等同於同時提供讀取和寫入權限。

權限

由於 Android 會使用沙箱隔離應用程式,因此應用程式必須明確共用資源和資料。方法是針對基本沙箱未提供的其他功能宣告所需權限,包括相機等裝置功能的存取權。

權限要求

盡量減少應用程式要求的權限數量。限制機密權限的存取權可降低不小心濫用這些權限的風險、提升使用者採用率,並降低應用程式遭受攻擊的風險。一般來說,如果應用程式不需要某項權限也能運作,就不應要求該權限。請參閱評估應用程式是否需要宣告權限指南。

請盡可能以不需要任何權限的方式設計應用程式。舉例來說,您可以為應用程式建立 UUID,而不要要求存取裝置資訊來建立專屬 ID (請參閱使用者資料一節)。或者,相較於使用外部儲存空間 (需要權限),將資料儲存於內部儲存空間。

除了要求權限以外,應用程式也可以使用 <permission> 元素保護安全敏感且會暴露給其他應用程式的 IPC,例如 ContentProvider。一般而言,建議您盡量不要使用使用者確認的權限,因為權限可能會對使用者造成混淆。例如,對於單一開發人員提供的應用程式之間的 IPC 通訊權限,請考慮使用簽名防護等級

請勿洩漏受權限保護的資料。如果應用程式透過僅在可用的 IPC 公開資料,因為應用程式擁有存取這些資料的權限,就會發生這種狀況。應用程式 IPC 介面的用戶端可能沒有相同的資料存取權限。如要進一步瞭解這個問題的頻率和潛在影響,請參閱《 權限重新委派:攻擊與防禦機制 》研究報告,這份研究報告發布於 USENIX。

權限定義

請定義符合安全性需求的最低權限組合。對於大多數應用程式來說,建立新權限並不常見,因為系統定義的權限已因應許多情況。在適當情況下,請使用現有權限執行存取權檢查。

如果您需要新權限,請考慮是否可以使用簽名保護等級來完成工作。簽章權限的內容對使用者是透明的,且只有相同開發人員所簽署的應用程式 (做為執行權限檢查的應用程式所簽署) 才能存取。

如果仍需建立新權限,請使用 <permission> 元素,在應用程式資訊清單中宣告權限。如要參照新權限的應用程式,可以在資訊清單檔案中加入 <uses-permission> 元素。您也可以使用 addPermission() 方法動態新增權限。

如果您使用危險防護等級建立權限,則需要考量一些複雜的操作:

  • 權限必須包含一個字串,以簡潔明瞭的方式向使用者說明必須做出的安全性決定。
  • 權限字串必須翻譯成多種不同的語言。
  • 使用者可能會因為權限混淆或認為有風險,因此選擇不安裝應用程式。
  • 應用程式可能會在權限建立者尚未安裝的情況下要求權限。

上述每個項目對開發人員來說都是一項重大的非技術挑戰,同時也會讓使用者感到困惑,因此不建議使用危險權限等級。

網路

網路交易本身就有安全性風險,因為這類交易涉及傳輸使用者的私人資料。使用者越來越重視行動裝置的隱私權疑慮,尤其在裝置執行網路交易時更是如此,因此應用程式請務必採用所有最佳做法,讓使用者的資料隨時安全無虞。

IP 網路

Android 的網路與其他 Linux 環境沒有顯著差異。重點是確保為機密資料使用合適的通訊協定,例如用 HttpsURLConnection 提供安全網路流量。在伺服器支援 HTTPS 的情況下,一律透過 HTTP 使用 HTTPS,因為行動裝置經常連線至不安全的網路,例如公用 Wi-Fi 無線基地台。

使用 SSLSocket 類別即可輕鬆實作經過驗證的加密通訊端層級通訊。考慮到 Android 裝置透過 Wi-Fi 連線到不安全的無線網路,強烈建議您對所有透過網路進行通訊的應用程式使用安全網路。

部分應用程式會使用 localhost 網路通訊埠處理敏感的 IPC。請勿使用這個方法,因為裝置上的其他應用程式也可以存取這些介面。請改用 Android IPC 機制,以便進行驗證,例如透過 Service。繫結至非特定 IP 位址 INADDR_ANY 比使用回送還差,因為這樣做可讓應用程式接收來自任何 IP 位址的要求。

請確保您不信任從 HTTP 或其他不安全的通訊協定下載的資料。這包括驗證 WebView 中的輸入,以及針對 HTTP 發出意圖的任何回應。

電話網路

簡短訊息服務 (SMS) 通訊協定主要是專為使用者之間的通訊而設計,並不適用於想要傳輸資料的應用程式。由於簡訊限制,建議您使用 Firebase 雲端通訊 (FCM) 和 IP 網路,將資料訊息從網路伺服器傳送到使用者裝置上的應用程式。

請注意,簡訊不會經過加密,也不會在網路或裝置上經過高度驗證。特別是,任何簡訊接收器都應預期惡意使用者可能將簡訊傳送到您的應用程式。請勿仰賴未經驗證的簡訊資料來執行機密指令。另請注意,簡訊可能會遭到網路冒用及/或攔截。在 Android 裝置上,簡訊會做為廣播意圖傳輸,因此其他具備 READ_SMS 權限的應用程式可讀取或擷取訊息。

輸入內容驗證

無論應用程式在哪個平台執行,輸入驗證不足是影響應用程式最常見的安全性問題之一。Android 提供平台層級因應措施,可降低應用程式出現輸入驗證問題的風險,我們建議您盡可能使用這些功能。此外,建議您使用類型安全的語言,降低輸入驗證問題的可能性。

如果您使用原生程式碼,從檔案讀取、透過網路或 IPC 接收的任何資料都可能會導致安全性問題。最常見的問題是緩衝區溢位釋放後使用差一錯誤。Android 提供多種技術 (例如 ASLR 和資料執行防範 (DEP)) 可降低這類錯誤的利用性,但依然無法解決潛在的問題。不過,請務必謹慎處理指標及管理緩衝區,藉此防止安全漏洞。

以字串為基礎的動態語言 (例如 JavaScript 和 SQL) 也可能會因逸出字元和插入指令碼而出現輸入驗證問題。

如果您使用提交至 SQL 資料庫或內容供應器的查詢中的資料,SQL 插入可能會造成問題。最好的預防方式是使用參數化查詢,詳情請參閱「內容供應器」一節。限制只有唯讀或寫入權限,也可以減少 SQL 插入作業造成的損害。

如果您無法使用本節所述的安全性功能,請務必使用完善的結構化資料格式,並驗證資料是否符合預期格式。封鎖特定字元或執行替換字元或許是一個有效的策略,但這些技巧在實務上很容易出錯,因此建議您盡可能避免使用這些方式。

使用者資料

一般來說,保護使用者資料的最佳做法,就是盡量避免使用會存取敏感或個人資料的 API。如果您可以存取使用者資料,請盡可能避免儲存或傳輸資料。請考量您的應用程式邏輯是否能使用雜湊或無法復原的資料形式實作。舉例來說,應用程式可能會使用電子郵件地址的雜湊做為主鍵,以避免傳輸或儲存電子郵件地址。這種做法可以降低資料不慎外洩的風險,也能降低攻擊者企圖惡意運用應用程式的可能性。

如果您的應用程式會存取密碼或使用者名稱等個人資訊,請注意,某些管轄區可能會要求您提供隱私權政策,說明您如何使用及儲存這些資料。遵循安全性最佳做法,盡量減少存取使用者資料,也有助於簡化法規遵循作業。

此外,也請考慮您的應用程式是否在無意間將個人資訊公開給其他第三方,例如廣告用的第三方元件或第三方服務。如果您不知道元件或服務為何需要個人資訊,請勿提供相關資訊。一般來說,減少應用程式存取個人資訊的做法,可降低此區域發生問題的可能性。

如果應用程式需要存取機密資料,請評估是否需要將其傳輸至伺服器,或者是否能在用戶端執行作業。建議你在用戶端執行任何使用機密資料的程式碼,以免傳輸使用者資料。此外,請確保您不會透過過於寬鬆的 IPC、世界可寫入的檔案或網路通訊端,在無意間將使用者資料暴露給裝置上的其他應用程式。過於寬鬆的處理序間通訊 (IPC) 是揭露受權限保護資料的特殊案例,詳情請參閱權限要求一節。

如果需要全域唯一識別碼 (GUID),請建立一個較大的專屬編號並儲存起來。請勿使用可能與個人資訊相關聯的手機 ID,例如電話號碼或 IMEI。如要進一步瞭解這個主題,請前往專屬 ID 最佳做法頁面。

寫入裝置上的記錄時,請務必小心。在 Android 上,記錄是共用資源,任何擁有 READ_LOGS 權限的應用程式皆可使用。即使手機記錄資料是暫時性的資料,在重新啟動時就會遭到清除,但不當的使用者資訊記錄仍可能意外將使用者資料洩露給其他應用程式。除了記錄 PII 外,也限制實際工作環境應用程式的記錄用量。如要輕鬆實作這項設定,請使用偵錯旗標和自訂 Log 類別,並搭配可輕鬆設定的記錄層級。

WebView

WebView 會使用包含 HTML 和 JavaScript 的網頁內容,因此不當使用可能會導致常見的網路安全性問題,例如 跨網站指令碼攻擊 (JavaScript 插入)。Android 內建許多機制,可將 WebView 的功能限制為應用程式所需的最低功能,藉此降低這類潛在問題的範圍。

如果您的應用程式沒有直接在 WebView 中使用 JavaScript,請「不要」呼叫 setJavaScriptEnabled()。部分程式碼範例使用這個方法;如果您在正式版應用程式中重複使用程式碼的程式碼範例,請移除該方法呼叫 (如果非必要的話)。根據預設,WebView 不會執行 JavaScript,因此無法使用跨網站指令碼。

請特別留意 addJavaScriptInterface() 的使用方式,因為這個做法可讓 JavaScript 叫用通常為 Android 應用程式保留的作業。如要使用,請只對所有輸入值得信任的網頁公開 addJavaScriptInterface()。如果允許不受信任的輸入來源,不受信任的 JavaScript 可能得以叫用應用程式中的 Android 方法。一般而言,建議只對應用程式 APK 中包含的 JavaScript 公開 addJavaScriptInterface()

如果您的應用程式透過 WebView 存取機密資料,請考慮使用 clearCache() 方法刪除儲存在本機的任何檔案。您也可以使用伺服器端標頭 (例如 no-store),指出應用程式不應快取特定內容。

如果裝置搭載 Android 4.4 (API 級別 19) 以下版本,則使用的 webkit 版本有多項安全性問題。為解決這個問題,如果應用程式在這類裝置上執行,必須確認 WebView 物件只顯示可信任的內容。為確保您的應用程式不會接觸到安全資料傳輸層 (SSL) 中的潛在安全漏洞,請按照「更新安全性提供者防範安全資料傳輸層 (SSL) 漏洞」一文所述,使用可更新的安全性 Provider 物件。如果您的應用程式必須轉譯開放網路的內容,建議您提供自己的轉譯器,讓轉譯器擁有最新的安全性修補程式。

憑證要求

為了讓網路釣魚攻擊更顯而易見,降低成功機率,請盡量降低要求使用者憑證的頻率。而是改用授權權杖並重新整理。

盡可能不要在裝置上儲存使用者名稱和密碼。 而是改用使用者提供的使用者名稱和密碼進行初始驗證,然後使用短期的服務專屬授權權杖。

建議您使用 AccountManager 連線至多個應用程式可存取的服務。盡可能使用 AccountManager 類別叫用雲端式服務,且不要將密碼儲存在裝置上。

使用 AccountManager 擷取 Account 後,請先使用 CREATOR 再傳入任何憑證,以免您不小心將憑證傳遞至錯誤的應用程式。

如果只有您建立的應用程式會使用憑證,您可以使用 checkSignatures() 驗證存取 AccountManager 的應用程式。或者,如果只有一個應用程式使用憑證,則可以使用 KeyStore 儲存憑證。

密碼學

Android 除了提供資料隔離功能、支援完整檔案系統加密、提供安全通訊管道,還提供一系列演算法,使用密碼編譯保護資料。

瞭解軟體使用的 Java Cryptography Architecture (JCA) 安全性供應商。請嘗試使用現有架構實作的最高層級,以支援您的用途。在適用情況下,請按照 Google 指定的順序使用 Google 提供的供應商。

如要更安全地讀取及寫入本機檔案,請使用 Security 程式庫

如果您需要從已知的網路位置安全地擷取檔案,也許只要簡單的 HTTPS URI 就夠了,也不需要密碼編譯方面的知識。如果需要安全通道,請考慮使用 HttpsURLConnectionSSLSocket,而非自行編寫通訊協定。如果您使用的是 SSLSocket,請注意,該方法不會執行主機名稱驗證。請參閱「直接使用 SSLSocket 的警告」。

如果您發現需要實作自己的通訊協定,請勿實作自己的密碼編譯演算法。使用現有的加密編譯演算法,例如 Cipher 類別中提供的 AES 和 RSA。此外,請按照下列最佳做法操作:

  • 將 256 位元 AES 用於商業用途。(如果無法使用,請使用 128 位元 AES)。
  • 針對橢圓曲線 (EC) 密碼編譯使用 224 位元或 256 位元公開金鑰大小。
  • 瞭解 CBC、點閱率或 GCM 區塊模式的使用時機。
  • 在點閱率模式中避免重複使用無效流量/計數器。而且務必以隨機的方式加密。
  • 使用加密功能時,請以 CBC 或點閱率模式搭配下列任一函式實作完整性:
    • HMAC-SHA1
    • HMAC-SHA-256
    • HMAC-SHA-512
    • GCM 模式

使用安全的隨機號碼產生器 SecureRandom,初始化 KeyGenerator 產生的任何加密編譯金鑰。如果使用的金鑰不是以安全隨機號碼產生器產生的金鑰,會大幅降低演算法的強度,並可能允許離線攻擊。

如果需要儲存金鑰以便重複使用,請使用 KeyStore 之類的機制,以便長期儲存及擷取加密編譯金鑰。

處理序間通訊

部分應用程式會嘗試使用傳統 Linux 技術 (例如網路通訊端和共用檔案) 實作 IPC。不過,建議您改將 Android 系統功能用於處理序間通訊 (IPC),例如 IntentBinderMessenger,並搭配 ServiceBroadcastReceiver。 Android IPC 機制可讓您驗證連線至 IPC 的應用程式身分,並設定每個處理序間通訊 (IPC) 機制的安全性政策。

許多安全性元素在處理序間通訊 (IPC) 機制間共用。如果您的 IPC 機制並非供其他應用程式使用,請在元件的資訊清單元素 (例如適用於 <service> 元素) 中將 android:exported 屬性設為 false。這對於在相同 UID 中由多個程序組成的應用程式而言非常有用,或者如果您在開發的後期決定不要將功能公開為 IPC,但是不想重新編寫程式碼。

如果其他應用程式可以存取您的 IPC,您可以使用 <permission> 元素套用安全性政策。如果 IPC 介於您擁有的應用程式之間,並使用相同金鑰簽署,請在 android:protectionLevel 中使用 signature 層級權限。

情境

對於活動和廣播接收器,意圖是 Android 上非同步 IPC 的偏好機制。視應用程式需求而定,您可以使用 sendBroadcast()sendOrderedBroadcast() 或特定應用程式元件的明確意圖。基於安全考量,建議使用明確意圖。

注意:如果您使用意圖繫結至 Service,請使用明確意圖來維持應用程式安全。使用隱含意圖啟動服務是一種安全危害,因為您無法確定哪個服務會回應意圖,而使用者也無法查看啟動哪個服務。從 Android 5.0 (API 級別 21) 開始,如果您在使用隱含意圖呼叫 bindService() 時,系統將擲回例外狀況。

請注意,有排序的廣播可以由接收者「消耗」,因此可能不會傳送給所有應用程式。如果您傳送必須傳遞至特定接收器的意圖,就必須使用明確宣告該接收器名稱的明確意圖。

意圖傳送者可以使用方法呼叫指定非空值權限,藉此驗證收件者是否擁有權限。只有具備該權限的應用程式會接收意圖。如果廣播意圖中的資料可能有機密性,建議您套用權限,確保惡意應用程式無法在沒有適當權限的情況下註冊,才能接收這些訊息。在這種情況下,您也可以考慮直接叫用接收器,而不要引發廣播。

注意:意圖篩選器並非安全性功能。您可以使用明確意圖叫用元件,也可能沒有符合意圖篩選器的資料。如要確認其為叫用的接收器、服務或活動格式正確,請在意圖接收器中執行輸入驗證。

服務

Service 通常用於提供功能給其他應用程式使用。每個服務類別的資訊清單檔案中都必須有對應的 <service> 宣告。

根據預設,服務不會匯出,也無法由任何其他應用程式叫用。但是,如果您在服務宣告中加入任何意圖篩選器,系統預設會匯出篩選器。因此,建議您明確宣告 android:exported 屬性,確保其運作方式符合預期。 您也可以使用 android:permission 屬性保護服務。這麼一來,其他應用程式必須在自己的資訊清單中宣告對應的 <uses-permission> 元素,才能啟動、停止或繫結至服務。

注意:如果應用程式指定的是 Android 5.0 (API 級別 21) 以上版本,請使用 JobScheduler 執行背景服務。

服務可以保護經由權限傳入的個別處理序間通訊 (IPC) 呼叫。方法是在執行呼叫實作之前呼叫 checkCallingPermission()。建議您在資訊清單中使用宣告式權限,因為這類權限較不容易遭到監督。

注意:請勿混淆用戶端和伺服器權限;請確認呼叫的應用程式具備適當的權限,並驗證您是否將相同權限授予呼叫應用程式。

繫結機制和 Messenger 介面

使用 BinderMessenger 是 Android 上遠端程序呼叫 (RPC) 樣式 IPC 的偏好機制。這些 API 提供定義完善的介面,可視需要啟用端點雙向驗證。

建議您在設計應用程式介面時,不要要求特定介面的權限檢查,BinderMessenger 物件不會在應用程式資訊清單中宣告,因此無法直接套用宣告式權限。通常會繼承實作 ServiceActivity 應用程式資訊清單中宣告的權限。如果您建立的介面需要驗證和/或存取權控管,則必須在 BinderMessenger 介面中明確將這些控制項新增為程式碼。

如果您提供的介面需要存取權控管機制,請使用 checkCallingPermission() 驗證呼叫端是否具備必要權限。尤其是在代表呼叫者存取服務前,這一點特別重要,因為應用程式的身分會傳遞至其他介面。如果您叫用 Service 提供的介面,如果沒有存取指定服務的權限,bindService() 叫用可能會失敗。如果您需要允許外部程序與應用程式互動,但是沒有必要的權限,您可以使用 clearCallingIdentity() 方法。這個方法會呼叫應用程式介面,就如同應用程式本身發出呼叫,而非外部呼叫。您稍後可以使用 restoreCallingIdentity() 方法還原呼叫端權限。

如要進一步瞭解如何使用服務執行 IPC,請參閱「繫結服務」。

廣播接收器

BroadcastReceiver 會處理 Intent 發起的非同步要求。

根據預設,接收器會匯出,並可由任何其他應用程式叫用。如果您的 BroadcastReceiver 是供其他應用程式使用,您可能需要使用應用程式資訊清單中的 <receiver> 元素,將安全性權限套用至接收器。這樣做可避免沒有適當權限的應用程式將意圖傳送至 BroadcastReceiver

透過動態載入的程式碼確保安全性

我們強烈建議您不要從應用程式 APK 以外的位置載入程式碼。這麼做會大幅提高應用程式因程式碼插入或竄改程式碼而遭駭的可能性。這也會增加版本管理和應用程式測試的複雜度,而且可能會使應用程式無法驗證應用程式行為,因此在某些環境中可能會遭到禁止。

如果您的應用程式會動態載入程式碼,請務必留意,動態載入的程式碼執行時會採用與應用程式 APK 相同的安全性權限。使用者會根據您的身分決定安裝應用程式,而使用者會預期您提供在應用程式中執行的任何程式碼,包括動態載入的程式碼。

許多應用程式會嘗試從不安全的位置載入程式碼,例如透過未加密的通訊協定從網路下載程式碼,或從外部儲存空間等可寫入的位置。這些位置可讓網路中的其他人修改傳輸的內容,或使用者裝置上的其他應用程式,修改裝置上的內容。另一方面,直接納入 APK 的模組無法由其他應用程式修改。無論程式碼是原生程式庫,還是使用 DexClassLoader 載入的類別都一樣。

虛擬機器的安全性

Dalvik 是 Android 的執行階段虛擬機器 (VM)。Dalvik 是專為 Android 打造而成,但其他虛擬機器中安全程式碼的相關疑慮,也適用於 Android。一般而言,您無須擔心虛擬機器的安全性問題。您的應用程式會在安全的沙箱環境中執行,因此系統中的其他程序無法存取您的程式碼或私人資料。

如要進一步瞭解虛擬機器安全性,請熟悉一些與主題相關的現有文獻。以下是兩個比較熱門的資源:

本文件著重說明 Android 專屬或與其他 VM 環境不同的領域。如果開發人員曾在其他環境中進行 VM 程式設計,則針對 Android 編寫應用程式可能會遇到以下兩個大問題:

  • 某些虛擬機器 (例如 JVM 或 .NET 執行階段) 可做為安全性邊界,用來區隔程式碼與基礎作業系統的功能。在 Android 上,Dalvik VM 並不是安全邊界,而是在 OS 層級實作應用程式沙箱,因此 Dalvik 可以與相同應用程式中的原生程式碼互通,沒有任何安全性限制。
  • 由於行動裝置上的儲存空間有限,開發人員往往會想建構模組化應用程式並使用動態類別載入。因此,請考量擷取應用程式邏輯的來源,以及應用程式邏輯儲存在本機的位置。請勿使用從未經驗證的來源 (例如不安全的網路來源或外部儲存空間) 載入的動態類別,因為這類程式碼可能會遭到修改,出現惡意行為。

原生程式碼的安全性

一般來說,建議您使用 Android SDK 開發應用程式,而不要使用原生程式碼搭配 Android NDK。使用原生程式碼建構的應用程式較為複雜、可攜性較低,也包括出現常見的記憶體損毀錯誤,例如緩衝區溢位。

Android 是以 Linux 核心為基礎建構而成,若您使用原生程式碼,熟悉 Linux 開發安全性最佳做法會更加實用。Linux 安全性做法不在本文件的討論範圍內,但最常見的資源之一是安全程式設計教學 - 建立安全軟體

Android 和大部分 Linux 環境之間的重要差異在於應用程式沙箱。在 Android 中,所有應用程式均會在應用程式沙箱中執行,包括以原生程式碼編寫的應用程式。如果開發人員熟悉 Linux,不妨先瞭解每個應用程式都有一個專屬的使用者 ID (UID),而且沒有權限限制。在 Android 安全性總覽中進一步瞭解相關詳情。即使您使用的是原生程式碼,也應熟悉應用程式權限。