行動應用程式處理越來越敏感的資料——銀行憑證、健康記錄、私人通訊和商業文件。與在您控制的伺服器上執行安全邏輯的網頁應用程式不同,行動應用程式運行在您無法控制的裝置上,在您無法信任的環境中,被可能成為複雜攻擊者目標的使用者存取。這一根本差異需要不同的安全方法。
行動應用程式安全不僅僅是防止未經授權的存取。它涉及保護裝置上的靜態資料、保護透過不可信網路傳輸的資料、防止應用程式邏輯的逆向工程,以及防禦執行時操縱。每個挑戰都需要特定的架構決策和仔細規劃。
本文涵蓋 iOS 和 Android 平台的基本行動安全架構。我們將研究安全資料儲存策略、網路通訊保護、程式碼混淆方法、執行時安全模式和身分驗證設計。透過架構原則和實際場景,我們將建立對行動安全基礎的全面理解。
安全資料儲存架構
行動裝置在敵對環境中儲存資料。使用者遺失手機、惡意軟體感染裝置、攻擊者獲得實體存取權限。即使裝置本身受到威脅,您的應用程式也必須保護敏感資料。
儲存層次結構
行動平台提供多種具有不同安全特性的儲存機制:
📦 儲存選項和安全層級
iOS 儲存機制
- UserDefaults:未加密,僅適用於非敏感偏好設定
- Keychain:硬體支援的加密,最適合憑證和金鑰
- 檔案系統:使用資料保護 API 加密
- Core Data:使用資料保護時加密
Android 儲存機制
- SharedPreferences:預設未加密,避免用於敏感資料
- Keystore:硬體支援的加密,最適合加密金鑰
- 內部儲存:應用程式私有但預設未加密
- EncryptedSharedPreferences:加密偏好設定(Android 6.0+)
- Room 資料庫配合 SQLCipher:加密資料庫儲存
關鍵原則:無論多麼方便,永遠不要在未加密的儲存中儲存敏感資料。
平台提供的安全性:正確的選擇
iOS Keychain 和 Android Keystore 提供硬體支援的加密,遠優於您可能實作的任何應用程式層級加密。這些系統利用安全飛地和可信執行環境,將加密金鑰儲存在甚至作業系統都無法存取的硬體中。
🔑 為什麼平台 API 更勝一籌
硬體支援的安全性
- 金鑰儲存在安全硬體中
- 在可信環境中執行加密操作
- 防止實體攻擊
- 作業系統層級存取控制
正確的金鑰管理
- 金鑰永不暴露給應用程式
- 自動金鑰輪換支援
- 安全金鑰衍生
- 可用生物辨識綁定
經過實戰檢驗的實作
- 經過安全專家審查
- 定期安全更新
- 符合標準
- 跨裝置廣泛測試
自訂加密實作會引入漏洞。硬編碼金鑰、弱演算法、不當的初始化向量和有缺陷的金鑰衍生是常見錯誤。平台 API 消除了這些風險。
可存取性和備份考量
資料可存取性決定了加密資料何時可用以及是否備份到雲端服務。這些決策在安全性和可用性之間取得平衡。
在 iOS 上,Keychain 可存取性選項控制資料何時可存取以及是否包含在備份中。最安全的選項——僅在解鎖時可存取且永不備份——提供最大保護,但可能限制背景功能。限制較少的選項啟用背景任務,但如果裝置受到威脅,則會增加暴露風險。
Android 的 Keystore 提供類似的控制。金鑰可以要求使用者身分驗證、綁定到特定時間段或限制為特定的加密操作。EncryptedSharedPreferences 自動處理加密,但需要仔細設定以從備份中排除敏感資料。
⚠️ 常見儲存錯誤
永不以明文儲存
- 不要使用 UserDefaults/SharedPreferences 儲存密碼
- 不要在程式碼或設定檔中儲存 API 金鑰
- 不要將敏感資料記錄到主控台
避免自訂加密
- 不要實作自己的加密演算法
- 不要使用硬編碼的加密金鑰
- 不要使用弱演算法(DES、MD5、SHA1)
備份考量
- 敏感資料可能備份到雲端
- 在 iOS 上使用「ThisDeviceOnly」可存取性
- 從 Android 備份中排除敏感檔案
網路安全架構
行動應用程式透過不可信網路通訊——公共 WiFi、行動網路、受損路由器。每個網路請求都是攔截或操縱的機會。
超越 HTTPS:縱深防禦
僅使用 HTTPS 是不夠的。適當的網路安全需要多層:TLS 設定、憑證驗證、憑證固定和請求簽章。
TLS 設定決定您的應用程式接受哪些協定版本和加密套件。支援過時的協定(如 TLS 1.0)或弱加密套件會使使用者暴露於已知攻擊。現代應用程式應強制使用 TLS 1.2 或更高版本,並使用強加密套件。
憑證驗證確保您與合法伺服器通訊。iOS 和 Android 提供的預設驗證通常足夠,但應用程式可以實作額外檢查。憑證固定——驗證特定憑證或公開金鑰——提供針對受損憑證授權機構的保護,但引入了操作複雜性。
請求簽章添加加密證明,證明請求未被竄改。即使透過 HTTPS,請求簽章也能防止某些類別的攻擊並提供不可否認性。基於 HMAC 的簽章使用共享金鑰或使用公開金鑰加密的非對稱簽章都可以運作,各有不同的權衡。
🚫 網路安全錯誤
停用憑證驗證
- 永不在正式環境中停用 SSL 驗證
- 不要信任所有憑證
- 不要忽略憑證錯誤
允許明文流量
- 不要在正式應用程式中允許 HTTP
- 對所有連線強制使用 HTTPS
- 使用 App Transport Security(iOS)/網路安全設定(Android)
弱 TLS 設定
- 不要支援 TLS 1.0 或 1.1
- 避免弱加密套件
- 將最低 TLS 版本保持在 1.2 或更高
憑證固定:來自實戰的教訓
憑證固定承諾增強安全性,但引入了操作風險。設定錯誤的固定或過期憑證可能使應用程式無法使用。憑證固定文章深入探討了這些權衡,但關鍵教訓是:在所有環境中徹底測試啟用固定的情況。
在憑證輪換期間,我們的測試團隊在 UAT 中停用了固定,因為「太難測試」。他們執行了完整的測試套件並報告成功——但固定被停用了,所以他們沒有驗證任何關於正式環境行為的內容。只有啟用固定的單獨預發布環境才發現了問題:新憑證使用了與我們固定邏輯不符的萬用字元通用名稱。
✅ 網路安全原則
強制使用強 TLS
- 最低 TLS 1.2
- 僅使用強加密套件
- 使用平台安全設定
正確驗證憑證
- 使用平台驗證作為基準
- 僅在合理時新增固定
- 在所有環境中測試固定
簽署關鍵請求
- 防止竄改
- 包含時間戳記以防止重放
- 使用常數時間比較
- 在伺服器端驗證
程式碼保護策略
行動應用程式分發給可能嘗試逆向工程的使用者。雖然完美的保護是不可能的,但您可以顯著提高門檻。
混淆:減慢攻擊者速度
程式碼混淆將可讀程式碼轉換為功能等效但難以理解的程式碼。類別名稱變成單個字母,方法名稱變成無意義的字串,控制流程變得複雜。混淆不能防止逆向工程——有決心的攻擊者會成功——但它增加了所需的時間和技能。
由於 Java 位元組碼的可讀性,Android 應用程式特別容易受到攻擊。ProGuard 和 R8 提供混淆、壓縮和最佳化。正確設定後,它們會刪除除錯資訊、重新命名類別和方法,並消除未使用的程式碼。
iOS 應用程式編譯為原生程式碼,本質上比 Android 的位元組碼更難逆向工程,但混淆仍然有幫助。字串加密隱藏 API 端點和設定。控制流程混淆使邏輯更難追蹤。符號剝離刪除除錯資訊。
🛡️ 混淆策略
要混淆的內容
- 業務邏輯和演算法
- API 端點和參數
- 內部類別和方法名稱
- 敏感字串常數
要保留的內容
- 公開 API 介面
- 透過反射使用的類別
- 原生方法宣告
- 序列化類別
測試要求
- 徹底測試發布版本
- 驗證當機報告可讀
- 檢查基於反射的程式碼是否運作
- 封存對應檔案以進行反混淆
混淆的局限性
混淆不是安全性。它是減速帶,不是牆。具有足夠動機和技能的攻擊者無論如何都會逆向工程您的應用程式。目標是使逆向工程足夠昂貴,以至於攻擊者追求更容易的目標,或者您在他們成功之前偵測到攻擊。
⚠️ 混淆局限性
不是真正的安全性
- 混淆減慢攻擊者速度,但不能阻止他們
- 有決心的攻擊者會逆向工程您的應用程式
- 不要依賴混淆來實現關鍵安全性
縱深防禦
- 將混淆與伺服器端驗證結合
- 使用執行時完整性檢查
- 實施速率限制和異常偵測
- 監控可疑行為
關鍵安全決策應在您控制環境的伺服器端進行。用戶端驗證是為了使用者體驗;伺服器端驗證是為了安全性。混淆保護智慧財產權並提高攻擊者的門檻,但它不能取代適當的安全架構。
UI 安全:保護可見資料
螢幕上顯示的敏感資料仍然容易受到截圖、螢幕錄製和應用程式切換器預覽的影響。UI 安全措施保護資料免受視覺擷取。
螢幕擷取防護
截圖和螢幕錄製可以擷取應用程式中顯示的敏感資訊。銀行應用程式、醫療保健應用程式和具有私人內容的訊息應用程式應防止敏感螢幕的螢幕擷取。
在 iOS 上,不直接支援防止截圖——平台優先考慮使用者控制。但是,您可以偵測何時截取截圖並做出適當回應,例如記錄事件或警告使用者。對於高度敏感的內容,考慮使用安全文字輸入欄位,這些欄位會自動從截圖中排除。
Android 提供 FLAG_SECURE 來防止截圖和螢幕錄製。此旗標將視窗標記為安全,防止其內容出現在截圖、螢幕錄製或非安全顯示器中。將此旗標套用於顯示敏感資訊的活動。
📸 螢幕擷取策略
何時防止擷取
- 銀行交易螢幕
- 醫療記錄和 PHI
- 私人訊息和通訊
- 付款資訊輸入
- 身分驗證螢幕
何時允許擷取
- 公開資訊螢幕
- 使用者擁有的使用者產生內容
- 設定和偏好
- 說明和文件
使用者體驗考量
- 告知使用者為何封鎖擷取
- 允許擷取非敏感螢幕
- 考慮無障礙需求
- 平衡安全性與可用性
應用程式切換器安全
當使用者在應用程式之間切換時,行動作業系統會顯示最近應用程式的預覽。這些預覽可能會向任何有實體存取裝置權限的人暴露敏感資訊。銀行餘額、私人訊息、醫療資料——都在應用程式切換器中可見。
iOS 和 Android 都會在應用程式移至背景時擷取快照。如果沒有保護,這些快照會顯示螢幕上的任何內容,可能會暴露敏感資料數小時或數天,直到應用程式重新開啟或裝置重新啟動。
解決方案是在擷取快照之前遮蓋敏感內容。當應用程式進入背景時顯示空白螢幕、啟動螢幕或通用佔位符。當應用程式返回前景時,恢復實際內容。
🔒 應用程式切換器保護策略
要隱藏的內容
- 帳戶餘額和財務資料
- 個人健康資訊
- 私人訊息和通訊
- 個人身分資訊
- 身分驗證螢幕
實作方法
- 顯示空白/白色螢幕
- 顯示應用程式標誌或啟動螢幕
- 顯示通用佔位符內容
- 模糊或像素化敏感區域
時機考量
- 在背景時立即套用保護
- 在前景時移除保護
- 處理快速應用程式切換
- 考慮動畫轉場
保護必須在系統擷取快照之前啟動。兩個平台都提供生命週期回呼,指示應用程式何時即將進入背景。透過在快照發生之前隱藏敏感內容來回應這些回呼。
平衡安全性和使用者體驗
UI 安全措施影響使用者體驗。防止截圖會讓試圖出於合法目的儲存資訊的使用者感到挫折。空白的應用程式切換器預覽使識別要返回的應用程式變得更加困難。關鍵是按比例套用這些保護。
高安全性螢幕——身分驗證、交易、敏感資料——證明採用積極保護是合理的。一般導覽、設定和公開資訊螢幕不需要相同層級的保護。根據顯示內容的敏感性有選擇地套用 UI 安全措施。
⚠️ UI 安全考量
不要過度保護
- 並非每個螢幕都需要擷取防護
- 使用者可能有合法的截圖理由
- 無障礙工具可能需要螢幕內容
- 平衡安全性與可用性
適當保護
- 識別真正敏感的螢幕
- 一致地套用保護
- 在保護啟動時告知使用者
- 在不同場景下測試
平台限制
- iOS 不支援截圖防護
- Android FLAG_SECURE 在已 root 裝置上可以被繞過
- 螢幕錄製應用程式可能規避保護
- 實體相機始終可以擷取螢幕
執行時安全架構
行動應用程式在您無法控制的環境中執行。適當地偵測和回應受損裝置。
偵測受損環境
Android 上的 root 偵測和 iOS 上的越獄偵測識別使用者具有提升權限的裝置。已 root 和已越獄的裝置可以繞過應用程式安全控制、存取受保護的資料並操縱應用程式行為。
偵測技術包括檢查已知的 root/越獄檔案、測試應用程式是否可以在其沙箱外寫入、偵測 root 管理應用程式以及檢查建置簽章。沒有偵測是完美的——複雜的攻擊者可以隱藏 root/越獄狀態——但基本檢查可以捕獲普通使用者和自動化攻擊。
偵錯器偵測識別應用程式何時在偵錯器下執行,攻擊者使用偵錯器來分析行為並繞過安全控制。檢查偵錯器附加、測試特定偵錯器工件以及監控可疑的時序模式都有助於偵測偵錯嘗試。
🔍 偵測回應策略
優雅降級
- 在受損裝置上停用敏感功能
- 向使用者顯示警告
- 限制功能而不是完全封鎖
靜默監控
- 將偵測事件記錄到分析
- 監控濫用模式
- 使用伺服器端風險評分
硬封鎖
- 拒絕在已 root/已越獄裝置上執行
- 僅適用於高安全性應用程式
- 向使用者提供清楚的解釋
回應策略很重要
您如何回應偵測到的威脅與偵測本身同樣重要。硬封鎖——拒絕在已 root 或已越獄裝置上執行——提供最大安全性,但會讓合法的進階使用者感到挫折。優雅降級——停用敏感功能同時允許基本功能——平衡安全性和可用性。靜默監控——記錄偵測而不進行使用者可見的變更——使基於風險的決策成為可能,而不會讓誤報影響使用者。
適當的回應取決於您的威脅模型和使用者群。銀行應用程式可能證明硬封鎖是合理的。社群媒體應用程式可能使用優雅降級。企業應用程式可能實施靜默監控和伺服器端風險評分。
身分驗證架構
身分驗證確定誰可以存取您的應用程式以及他們可以做什麼。行動身分驗證必須平衡安全性和可用性。
生物辨識身分驗證:安全性與可用性的結合
生物辨識身分驗證——指紋、臉部辨識、虹膜掃描——提供強大的安全性和出色的使用者體驗。使用者無需記住密碼即可快速進行身分驗證。生物辨識資料永不離開裝置,完全在安全硬體中處理。
平台生物辨識 API 處理生物辨識身分驗證的複雜性。iOS Face ID 和 Touch ID、Android BiometricPrompt——這些 API 在裝置之間提供一致的介面,處理回退到裝置憑證,並在安全飛地中保護生物辨識資料。
生物辨識身分驗證應該補充而不是取代傳統身分驗證。初始登入需要使用者名稱和密碼(或等效憑證)。生物辨識技術支援後續工作階段的快速重新身分驗證。這種方法提供安全性——受損的生物辨識技術不會授予永久存取權限——同時保持可用性。
🔐 身分驗證最佳實務
生物辨識身分驗證
- 專門使用平台 API
- 永不直接處理生物辨識資料
- 提供回退到裝置憑證
- 初始登入需要傳統身分驗證
權杖管理
- 在 Keychain/Keystore 中儲存權杖
- 實施權杖重新整理
- 登出時清除權杖
- 使用短期存取權杖
工作階段管理
- 實施適當的逾時
- 對敏感操作重新身分驗證
- 在背景清除工作階段資料
- 優雅地處理工作階段過期
多因素身分驗證
多因素身分驗證(MFA)需要多種形式的驗證:您知道的東西(密碼)、您擁有的東西(裝置、安全金鑰)、您是誰(生物辨識)。MFA 透過要求攻擊者破壞多個因素來顯著提高安全性。
行動應用程式非常適合 MFA。裝置本身充當佔有因素。推播通知支援輕鬆批准身分驗證嘗試。基於時間的一次性密碼(TOTP)提供額外驗證。生物辨識技術新增第三個因素。
實施 MFA 需要仔細的 UX 設計。過多的摩擦會促使使用者停用安全功能或放棄應用程式。漸進式身分驗證——僅對敏感操作要求額外因素——平衡安全性和可用性。
安全測試策略
測試安全實作與實作它們同樣重要。在理想條件下運作但在邊緣情況下失敗的安全性提供了虛假的信心。
在真實裝置上測試
模擬器和仿真器不能準確代表正式環境。安全功能在真實硬體上的行為不同。安全飛地、生物辨識感測器和硬體支援的金鑰庫僅存在於實體裝置上。在多個製造商和作業系統版本的真實裝置上進行測試。
測試失敗場景。當 Keychain 存取失敗時會發生什麼?當網路請求被攔截時?當裝置已 root 時?當生物辨識身分驗證不可用時?安全實作必須優雅地處理失敗,而不會暴露資料或當機。
永不在測試中停用安全性
在非正式環境中停用安全功能的誘惑很強,但它會破壞測試。如果在 UAT 中停用憑證固定,因為「太難測試」,UAT 就不會驗證任何關於固定行為的內容。第一次真正的測試變成了正式環境,失敗會影響使用者。
🚫 適得其反的測試捷徑
為什麼團隊在 UAT 中停用安全性
- 「憑證固定太難測試」
- 「我們在 UAT 中使用自簽憑證」
- 「固定失敗在測試中太常見」
- 「它減慢了我們的測試週期」
為什麼這會失敗
- 測試應驗證正式環境行為
- 如果難以測試,就難以操作
- 常見失敗表明真正的問題
- 緩慢的測試優於正式環境中斷
在所有環境中維護安全功能。是的,在 UAT 中管理憑證更難。是的,它需要團隊之間的協調。是的,它會減慢某些測試場景。但它可以防止正式環境災難。在測試環境中維護安全性的操作負擔遠小於影響數千或數百萬使用者的正式環境中斷的成本。
威脅建模和風險評估
在實施安全措施之前,了解您要防禦的威脅以及保護是否證明複雜性是合理的。
並非每個應用程式都需要每個安全功能
天氣應用程式與銀行應用程式有不同的安全要求。天氣應用程式可能跳過 root 偵測和程式碼混淆,專注於基本的 HTTPS 和使用者偏好的安全儲存。銀行應用程式證明全面安全是合理的:硬體支援的儲存、憑證固定、程式碼混淆、root 偵測和生物辨識身分驗證。
將安全投資與您的風險概況相符。考慮:
- 您的應用程式處理什麼敏感資料?
- 如果該資料被洩露,影響是什麼?
- 誰可能攻擊您的應用程式,為什麼?
- 潛在攻擊者擁有什麼資源?
- 實施和維護安全措施的成本是多少?
- 對使用者體驗的影響是什麼?
✅ 基於風險的安全決策
高安全性應用程式
- 銀行和金融服務
- 包含 PHI 的醫療保健
- 政府和國防
- 具有敏感資料的企業
中等安全性應用程式
- 具有私人訊息的社群媒體
- 具有付款資料的電子商務
- 具有使用者資料的生產力應用程式
低安全性應用程式
- 公開資訊應用程式
- 沒有購買的遊戲
- 沒有使用者資料的公用程式
縱深防禦
沒有單一的安全措施是足夠的。縱深防禦——多層保護——確保如果一層失敗,其他層提供保護。安全儲存保護靜態資料。TLS 保護傳輸中的資料。混淆減慢逆向工程。執行時偵測識別受損環境。伺服器端驗證捕獲用戶端繞過。
每一層都解決不同的威脅並具有不同的優勢。結合起來,它們創造的安全態勢大於各部分的總和。
運營安全考量
安全性不會在部署時結束。持續運營決定安全措施是否保持有效。
監控和事件回應
監控安全事件:root 偵測觸發、憑證驗證失敗、可疑的身分驗證模式、異常的 API 使用。這些事件表明潛在的攻擊或受損裝置。彙總監控資料以識別單個事件可能遺漏的模式。
準備好事件回應程序。當您偵測到受損裝置時會發生什麼?當憑證需要緊急輪換時?當發現漏洞時?記錄的程序使事件發生時能夠快速回應。
更新和修補
安全漏洞不斷被發現。平台安全 API 不斷演進。攻擊技術不斷進步。定期更新解決漏洞、採用新的安全功能並回應新興威脅。
實施機制以鼓勵或要求更新。關於關鍵安全更新的推播通知。對具有嚴重漏洞的應用程式強制執行最低版本。平衡安全需求與使用者體驗——強制更新會讓使用者感到挫折,但對於關鍵安全問題可能是必要的。
金鑰輪換和憑證管理
加密金鑰和憑證的生命週期有限。在過期之前計劃輪換。在非正式環境中測試輪換程序。為受損的金鑰或憑證準備緊急程序。
憑證固定需要特別仔細的管理。固定多個憑證或公開金鑰以支援輪換而無需應用程式更新。監控憑證過期日期。在部署之前測試新憑證。準備好回復程序。
結論
行動應用程式安全需要全面的架構來應對多個威脅向量。安全資料儲存保護靜態資訊,使用平台提供的機制(如 iOS Keychain 和 Android Keystore)而不是自訂加密。網路安全超越 HTTPS,包括適當的 TLS 設定、憑證驗證和請求簽章。透過混淆進行程式碼保護提高了逆向工程的門檻,儘管它不能阻止有決心的攻擊者。執行時安全偵測受損環境,允許應用程式適當地回應已 root 裝置和偵錯器。
行動安全的根本挑戰是應用程式在您無法控制的敵對環境中執行。使用者可能遺失裝置、安裝惡意軟體或成為複雜攻擊者的目標。您的安全模型必須假設裝置本身受到威脅,並實施縱深防禦——多層保護協同運作以最小化風險。
平台提供的安全機制幾乎總是優於自訂實作。iOS Keychain 和 Android Keystore 提供硬體支援的加密,遠比您可能實作的任何應用程式層級加密更安全。網路安全設定和 App Transport Security 以宣告方式強制執行 TLS 最佳實務,減少實作錯誤的風險。生物辨識身分驗證 API 提供安全、使用者友善的身分驗證,而無需您處理敏感的生物辨識資料。
安全性和可用性之間的平衡在行動應用程式中至關重要。過於激進的安全措施會讓使用者感到挫折,並促使他們轉向不太安全的替代方案。封鎖所有已 root 裝置的 root 偵測可能會阻止合法的進階使用者使用您的應用程式。過於頻繁地要求重新身分驗證的生物辨識身分驗證會變得令人討厭。目標是比例安全——將安全措施與資料的敏感性和操作的風險相符。
測試安全實作與實作它們同樣重要。在真實裝置上測試,而不僅僅是模擬器。使用各種作業系統版本進行測試,因為安全 API 會演進。測試失敗場景——當 Keychain 存取失敗時會發生什麼,當網路請求被攔截時,當裝置已 root 時?在理想條件下完美運作但在邊緣情況下災難性失敗的安全性提供了虛假的信心。永遠不要因為「太難」而在測試環境中停用安全功能——這種困難是您的早期警告系統。
行動安全不是一次性實作,而是一個持續的過程。新的漏洞被發現,平台不斷演進,攻擊技術不斷進步。隨時了解平台安全更新,監控您使用的程式庫的安全公告,並定期審查您的安全實作。行動安全格局變化迅速,昨天的最佳實務可能是今天的漏洞。
在實施任何安全措施之前,了解您要防禦的威脅以及保護是否證明複雜性是合理的。並非每個應用程式都需要 root 偵測或程式碼混淆。天氣應用程式與銀行應用程式有不同的安全要求。將您的安全投資與您的實際風險概況相符,並在新增進階保護之前專注於基礎——安全儲存、適當的 TLS 和強身分驗證。
行動應用程式安全具有挑戰性,因為您要在多個層面上防禦威脅——網路攻擊、裝置威脅、逆向工程和執行時操縱。但是,透過利用平台安全功能、實施縱深防禦以及透過測試和更新保持警惕,您可以建構即使在敵對環境中也能保護使用者資料的行動應用程式。裝置可能在使用者的口袋裡,但安全責任仍然是您的。