10個Android特性安全開發指南
這篇文章主要探討10個Android開發時的安全指南.
Android本質上為Java開發,除了Java安全編碼的安全規範要注意之外
Android本身有許多特性,例如Intent, Activity, SQLite等
這些特性在開發時要如何才能避免風險與弱點?
1. Activities
一般來如果該Activity不希望其它Application可以存取的話, 可以做下列處理
- 不要設定taskAffinity.
- 不要設定launchMode.
- 刻意設定exported為false
- 檢查內部Application接受到的intent
- 不要傳送敏感性資訊
2. Broadcasts
Broadcast receiver 分為三種private, public, in-house, 這邊舉private安全較高的來討論
private Broadcast receiver只能收到同一個application內的broadcasts
private Broadcast receivver安全開發處理時要注意:
- 名確定義 exported = “false”
- 驗證任何收到的intent訊息
- 敏感性資訊的傳送與接收
[pastacode lang=”markup” manual=”%3Creceiver%0Aandroid%3Aname%3D%22.PrivateReceiver%22%0Aandroid%3Aexported%3D%22false%22%20%2F%3E” message=”” highlight=”” provider=”manual”/]
3. Content Providers
Content Provider主要提供application之間的資料交換與分享
Content Provider有五種, 分別為private, public, partner, in-house, temp等
這裡舉最安全的private content provider 開發時要注意
- 明確定義exported = false
[pastacode lang=”markup” manual=”%3Cprovider%0Aandroid%3Aname%3D%22.PrivateProvider%22%0Aandroid%3Aauthorities%3D%22org.test.android.provider.privateprovider%22%0Aandroid%3Aexported%3D%22false%22%20%2F%3E” message=”” highlight=”” provider=”manual”/]
另外一種值得一提的是暫時性的Temporary Content Providers
這種方式可以讓特定Applicaiton存取特定的URI,
設定上除了要將 android:exported=”false”
另外還要設定可以存取的URI 例如
<grant-uri-permission android:path=”/books” />
4. Services
Service可分為四種,
- private:只能application內部存取
- public:可以讓其它application存取
- partner:可以讓特定信任公司app存取
- in-house:只能讓 in-house app存取
安全開發services的原則如下:
- 設定exported=false, 特別不同的是
<service android:name=”.PrivateStartService” android:exported=”false”/>
<service android:name=”.PrivateIntentService” android:exported=”false”/>
編碼時必須特別指定intent的
Intent intent = new Intent(this, PrivateStartService.class);
問題討論
- private service可否設定exported = false, 同時又設定intent-filter?
不行!. 比較安全的方式是只設定 exported = false
2.在創建 onCreate服務的時候檢查可以嗎?
不行! 因為服務執行的時候, 不一定會執行到 onCreate
5. SQLite
- 使用SQLiteOpenHelper創建SQLite (如果使用SQLiteDatabase#openOrCreateDatabase創建資料庫會導致該檔案可以被其它app存取)
- 使用 prepareStatement查詢SQL
- 當需要將數據庫資料與其它app共享時, 使用Content Provider
- 考慮使用數據庫加密sqlcipher https://guardianproject.info/code/sqlcipher/
- 將資料庫權限設定為MODE_PRIVATE (使用Context#openOrCreateDatabase)
[pastacode lang=”markup” manual=”db%20%3D%20Context.openOrCreateDatabase(%22Test.db%22%2C%0AMODE_PRIVATE%2C%20null)%3B” message=”” highlight=”” provider=”manual”/]
問題討論: 使用 SQL Statement 還是 Android API SQLiteDatabase#insert()/update()/delete()/query()/replace()?
- 使用SQL Statement 必須要做到 prepare statement
- 使用 Android提供的API對數據庫進行操作時, 將參數值透過ContentValues處理
6. 檔案的處理
app相互間的溝通應該要透過Content Provider或是Service.而不是檔案,這是基本的安全設計原則
- 檔案儲存在 Application路徑下是比較安全, 儲存在外部儲存媒體SD card因為沒有存取控管可以被其它App讀取與修改
- 敏感性資訊加密儲存或是不儲存
- 檔案創建的時候設定為 private mode
fileSample= openFileOutput(FILE_NAME, MODE_PRIVATE);
7. Browsable Intent
browsable intent主要功能為根據 URI啟動相對應的app
例如 fb:// 來啟動facebook, 這樣帶來便利性但是卻也有可能讓使用者誤安裝病毒
安全的設計必須要驗證該URI 所傳遞的參數
8. LogCat
LogCat 主要用在日誌記錄
Android LogCat的特性 development build 與release build 最大的差異在於release build沒有 debug, verbose資訊
- development build: Error, Warn, Info, Debug, Verbose
- release build: Error, Warn, Info
基本的安全設計原則是不要日誌記錄敏感性資訊
- 使用ProGuard將不必要的日誌記錄從程式碼中移除 Log.d()與 Log.v()
- 使用android.util.Log class不要用其它方式, 例如System.out/err
9.WebView
WebView主要的安全風險是JavaScript的執行
- 限定使用 HTTPS
- 如果可以限定可以訪問的URL白名單
- 設定檔案存取屬性 webSettings.setAllowFileAccess(false);
- SSL的錯誤處理, 分為證書過期, hostname不符合, 證書無效, CA的發送方不可靠等
10. Notifications
訊息主要是用來提示使用者相關系統狀態
安全風險在於這樣的隱私訊息提示有可能會被其它app讀取
訊息依照安全層級可以分為三種: public, private, secret
Notification.Builder privateNotificationBuilder = new Notification.Builder(this).setContentTitle(“Notification : Private”);
不管是哪一種層級都不建議將敏感性資訊透過訊息傳遞特別是 public的層級
因為在public訊息下, 該訊息在螢幕鎖定的狀態下依然會顯示