Android 安全性團隊經常收到有關防止 Android 裝置發生潛在安全性問題的資訊要求。我們也會不定期抽查裝置,並將潛在問題通知裝置製造商和受影響的合作夥伴。
本頁面提供根據我們的經驗歸納出的安全性最佳做法,擴充我們為開發人員提供的「Designing for Security」說明文件,並包含在裝置上建構或安裝系統層級軟體時的獨特詳細資料。
為協助您採用這些最佳做法,Android 安全團隊會盡可能將測試納入 Android Compatibility Test Suite (CTS) 和 Android Lint。我們鼓勵裝置導入者提供有助於其他 Android 使用者的測試 (請前往 root/cts/tests/tests/security/src/android/security/cts
查看安全性相關測試)。
開發流程
在開發程序和環境中採用下列最佳做法。
查看原始碼
原始碼審查可偵測各種安全性問題,包括本文所述的安全性問題。Android 強烈建議您同時進行手動和自動化原始碼審查。最佳做法:
- 請在使用 Android SDK 的所有應用程式程式碼上執行 Android Lint,並修正任何已識別的問題。
- 應使用可偵測記憶體管理問題的自動化工具 (例如緩衝區溢位和 off-by-one 錯誤) 來分析原生程式碼。
- Android 建構系統支援許多 LLVM 淨化器,例如可用於此目的 AddressSanitizer 和 UndefinedBehaviorSanitizer。
使用自動化測試
自動化測試可偵測多種安全性問題,包括下文所述的幾個問題。最佳做法:
- CTS 會定期更新安全性測試;請執行最新版的 CTS 來驗證相容性。
- 在開發過程中定期執行 CTS,以便提早偵測問題,縮短修正時間。Android 會在自動化建構程序中使用 CTS 作為持續整合的一部分,每天建構多次。
- 裝置製造商應自動化介面安全性測試,包括使用格式錯誤的輸入內容進行測試 (模糊測試)。
標誌系統圖片
系統映像檔的簽章對於判斷裝置完整性至關重要。最佳做法:
- 裝置不得使用公開金鑰進行簽署。
- 用於簽署裝置的金鑰應以符合業界標準處理機密金鑰的方式管理,包括提供可稽核的有限存取權的硬體安全性模組 (HSM)。
簽署應用程式 (APK)
應用程式簽名在裝置安全性方面扮演重要角色,可用於權限檢查和軟體更新。在選擇用於簽署應用程式的金鑰時,請務必考量應用程式是否只會在單一裝置上使用,或是會在多部裝置上共用。最佳做法:
- 應用程式不得使用公開金鑰簽署。
- 用於簽署應用程式的金鑰應以符合業界標準實務的方式管理,包括提供受限且可稽核存取權的 HSM。
- 應用程式不應使用平台金鑰簽署。
- 套件名稱相同的應用程式不應使用不同的金鑰簽署。這通常會發生在為不同裝置建立應用程式時,尤其是使用平台金鑰時。如果應用程式不受裝置限制,請在各裝置上使用相同的金鑰。如果應用程式是特定裝置專用,請為每個裝置和金鑰建立專屬的套件名稱。
發布應用程式
Google Play 可讓裝置製造商在不執行完整系統更新的情況下更新應用程式。這麼做可以加快安全性問題的回應速度,並提供新功能,同時確保應用程式擁有專屬的套件名稱。最佳做法:
- 將應用程式上傳至 Google Play,即可啟用自動更新功能,而無須進行完整的無線更新 (OTA)。已上傳但未發布的應用程式無法供使用者直接下載,但仍會更新。先前已安裝應用程式的使用者可以重新安裝應用程式,並/或在其他裝置上安裝。
- 建立與貴公司明確相關的應用程式套件名稱,例如使用公司商標。
- 裝置製造商發布的應用程式應上傳至 Google Play 商店,以免遭第三方使用者冒用套件名稱。如果裝置製造商在裝置上安裝應用程式,但未在 Play 商店發布應用程式,其他開發人員就可能上傳相同的應用程式,使用相同的套件名稱,並變更應用程式的中繼資料。當應用程式呈現給使用者時,這些不相關的中繼資料可能會造成混淆。
回應事件
外部單位必須能夠與裝置製造商聯絡,瞭解裝置相關的安全性問題。建議您建立可供大眾存取的電子郵件地址,用於管理安全性事件。最佳做法:
- 建立 security@your-company.com 或類似的電子郵件地址,並公開這項資訊。
- 如果您發現影響 Android 作業系統或多家裝置製造商的 Android 裝置的安全性問題,請提交 安全性錯誤報告,與 Android 安全性團隊聯絡。
實作產品
實作產品時,請採用下列最佳做法。
隔離根程序
根程序是權限提升攻擊最常鎖定的目標,因此減少根程序的數量,就能降低權限提升的風險。CTS 包含資訊測試,可列出根程序。最佳做法:
- 裝置應以 root 權限執行必要的最低程式碼。請盡量使用一般 Android 程序,而非根程序。ICS Galaxy Nexus 只有六個根源程序:vold、inetd、zygote、tf_daemon、ueventd 和 init。如果程序必須在裝置上以 root 權限執行,請在 AOSP 功能要求中記錄程序,以便公開審查。
- 請盡可能將根碼與不受信任的資料隔離,並透過 IPC 存取。舉例來說,您可以將根層級功能縮減為可透過 Binder 存取的小型服務,並將具有簽名權限的服務公開給應用程式,讓應用程式處理網路流量,但權限較低或沒有權限。
- 根程序不得監聽網路通訊端。
- 根程序不得為應用程式提供通用的執行階段 (例如 Java VM)。
隔離系統應用程式
一般來說,預先安裝的應用程式不應使用共用的系統 UID 執行。不過,如果應用程式需要使用系統或其他特權服務的共用 UID,則不應匯出任何服務、廣播接收器或內容供應器,以免使用者安裝的第三方應用程式可存取這些項目。最佳做法:
- 裝置應以系統模式執行必要的最低程式碼。盡可能使用具有自身 UID 的 Android 程序,而非重複使用系統 UID。
- 在可行情況下,系統程式碼應與不受信任的資料隔離,並只將 IPC 公開給其他受信任的程序。
- 系統程序不得監聽網路通訊端。
隔離程序
Android 應用程式沙箱可讓應用程式與系統上的其他程序 (包括根層級程序和偵錯工具) 隔離。除非應用程式和使用者特別啟用偵錯功能,否則任何應用程式都不得違反這項預期。最佳做法:
- 除非使用已記錄的 Android 偵錯方法,否則根程序不得存取個別應用程式資料資料夾中的資料。
- 除非使用已記錄的 Android 偵錯方法,否則根程序不得存取應用程式的記憶體。
- 裝置不得包含任何會存取其他應用程式或程序的資料或記憶體的應用程式。
保護 SUID 檔案
新的 setuid 程式不應由不信任的程式存取。Setuid 程式經常是可用於取得 root 存取權的漏洞所在位置,因此請盡量減少 setuid 程式對不受信任的應用程式可用性。最佳做法:
- SUID 程序不得提供可用於規避 Android 安全性模型的殼層或後門。
- SUID 程式不得允許任何使用者寫入。
- SUID 程式不應可供所有使用者讀取或執行。建立群組,並限制 SUID 二進位檔的存取權,只允許該群組成員存取,然後將任何可執行 SUID 程式的應用程式放入該群組。
- 使用者取得裝置 Root 權限的常見來源是 SUID 程式。為降低這類風險,請勿讓殼層使用者執行 SUID 程式。
CTS 驗證器包含資訊測試,列出 SUID 檔案;根據 CTS 測試,某些 setuid 檔案不允許使用。
安全的監聽 Socket
當裝置在任何介面上的任何通訊埠上進行偵聽時,CTS 測試會失敗。發生錯誤時,Android 會驗證是否採用下列最佳做法:
- 裝置上不應有任何監聽連接埠。
- 監聽通訊埠必須能夠在沒有 OTA 的情況下停用。這可能是伺服器或使用者裝置設定變更。
- 根程序不得監聽任何通訊埠。
- 系統 UID 擁有的程序不得監聽任何連接埠。
- 針對使用通訊端的本機 IPC,應用程式必須使用 UNIX 網域通訊端,並將存取權限制在群組內。為 IPC 建立檔案描述元,並將其設為特定 UNIX 群組的 +RW。所有用戶端應用程式都必須位於該 UNIX 群組中。
- 部分裝置具有多個處理器 (例如與應用程式處理器分開的無線電/數據機),會使用網路通訊端來在處理器之間進行通訊。在這種情況下,用於處理器間通訊的網路通訊端必須使用隔離的網路介面,以免遭到裝置上未經授權的應用程式存取 (也就是使用
iptables
避免遭到裝置上其他應用程式存取)。 - 處理監聽埠的 Daemon 必須能有效處理格式錯誤的資料。Google 可能會使用未經授權的用戶端,以及可行的話,也會使用經過授權的用戶端,針對該埠進行模糊測試。任何當機都會以適當嚴重性的錯誤記錄。
記錄檔資料
記錄資料會增加該資料外洩的風險,並降低系統效能。由於 Android 裝置預設安裝的應用程式會記錄敏感的使用者資料,因此發生多起公開安全性事件。最佳做法:
- 應用程式或系統服務不應記錄可能包含私密資訊的第三方應用程式所提供的資料。
- 應用程式不得在正常運作期間記錄任何個人識別資訊 (PII)。
CTS 包含測試,可檢查系統記錄中是否有潛在的機密資訊。
限制目錄存取權
可寫入的一般目錄可能會導致安全性弱點,並讓應用程式重新命名信任的檔案、替換檔案,或執行以符號連結為基礎的攻擊 (攻擊者可能會使用檔案的符號連結,誘騙信任的程式執行不該執行的動作)。可寫入的目錄也會導致解除安裝應用程式時無法正確清除與應用程式相關聯的所有檔案。
最佳做法是,由系統或 root 使用者建立的目錄不應允許所有使用者寫入。CTS 測試會測試已知的目錄,協助您落實這項最佳做法。
安全的設定檔
許多驅動程式和服務都會依賴設定和資料檔案,這些檔案儲存在 /system/etc
和 /data
等目錄中。如果這些檔案是由具有特殊權限的程序處理,且可供所有使用者寫入,應用程式就可能會在可供所有使用者寫入的檔案中製作惡意內容,進而利用程序中的漏洞。最佳做法:
- 特權程序使用的設定檔不應可供所有人讀取。
- 特權程序使用的設定檔不得開放給所有使用者寫入。
儲存原生程式碼資料庫
特權裝置製造商程序使用的任何程式碼,都必須位於 /vendor
或 /system
中;這些檔案系統會在開機時掛載為唯讀。最佳做法是,系統或裝置上安裝的其他高權限應用程式所使用的程式庫,也應位於這些檔案系統中。這麼做可避免安全漏洞,避免攻擊者控制特權程序執行的程式碼。
限制裝置驅動程式存取權
只有受信任的程式碼才應直接存取驅動程式。在可行情況下,建議架構是提供單一用途的守護程序,以便將對驅動程式的呼叫轉送至該守護程序,並限制驅動程式對該守護程序的存取權。最佳做法是,驅動程式裝置節點不應可供所有人讀取或寫入。CTS 測試會檢查已公開的驅動程式例項,以便強制執行這項最佳做法。
停用 ADB
Android Debug Bridge (adb) 是實用的開發和偵錯工具,但其設計用途是在受控的安全環境中使用,因此不應啟用供一般使用。最佳做法:
- 預設情況下必須停用 ADB。
- ADB 必須要求使用者先開啟,才能接受連線。
解鎖系統啟動載入程式
許多 Android 裝置都支援解鎖功能,可讓裝置擁有者修改系統分區和/或安裝自訂作業系統。常見的用途包括安裝第三方 ROM,以及在裝置上執行系統層級開發作業。舉例來說,Google Nexus 裝置的使用者可以執行 fastboot oem unlock
來啟動解鎖程序,並向使用者顯示下列訊息:
要解鎖系統啟動載入程式嗎?
解鎖系統啟動載入程式後,您就能在裝置上安裝自訂作業系統軟體。
自訂作業系統不會接受與原始作業系統相同的測試,且可能導致裝置和已安裝的應用程式停止正常運作。
為避免未經授權存取個人資料,解鎖系統啟動載入程式也會刪除裝置上的所有個人資料 (也就是「恢復原廠資料」)。
按下調高/調低音量鍵,選取「是」或「否」。然後按下電源鍵繼續。
是:解鎖系統啟動載入程式 (可能會失去保固)
否:請勿解鎖系統啟動載入程式,也不要重新啟動裝置。
最佳做法是,可解鎖的 Android 裝置必須在解鎖前,安全地清除所有使用者資料。如果無法妥善刪除解鎖時的所有資料,可能會讓鄰近的攻擊者未經授權存取機密 Android 使用者資料。為避免洩漏使用者資料,支援解鎖功能的裝置必須正確實作這項功能 (我們發現許多裝置製造商未正確實作解鎖功能)。正確實作的解鎖程序具有下列屬性:
- 使用者確認解鎖指令後,裝置必須立即開始清除資料。安全刪除作業完成後,才能設定
unlocked
標記。 - 如果無法完成安全刪除作業,裝置必須保持鎖定狀態。
- 如果底層區塊裝置支援,則應使用
ioctl(BLKSECDISCARD)
或等效的裝置。對於 eMMC 裝置,這表示使用安全擦除或安全修剪指令。對於 eMMC 4.5 以上版本,這表示使用一般清除或修剪作業,接著執行 Sanitize 作業。 - 如果基礎區塊裝置不支援
BLKSECDISCARD
,則必須改用ioctl(BLKDISCARD)
。在 eMMC 裝置上,這是正常的修剪作業。 - 如果不支援
BLKDISCARD
,則可以使用全零值覆寫區塊裝置。 - 使用者必須有權要求在刷新分割區之前,先清除使用者資料。舉例來說,在 Nexus 裝置上,這項操作是透過
fastboot oem lock
指令完成。 - 裝置可能會透過 efuse 或類似機制記錄裝置是否已解鎖和/或重新上鎖。
這些規定可確保系統在解鎖作業完成後銷毀所有資料。未實施這些防護措施,會被視為中度安全漏洞。
解鎖的裝置之後可能會使用 fastboot oem lock
指令重新上鎖。鎖定系統啟動載入程式後,新的自訂 OS 將提供與原始裝置製造商 OS 相同的使用者資料保護機制 (例如,如果裝置再次解鎖,使用者資料就會遭到清除)。