2017年1月2日 星期一

【Android】OMTG-DATAST-001: Test for Sensitive Data in Local Storage

#2017.10.10更新:因應OWASP MSTG架構大改,以下內容、文章標題會再做修改

0x00 簡介

Android App 在本機儲存資料時的四種儲存機制:

1.Shared Preferences:
  • 以 XML 格式儲存 key-value 資料
  • 檔案路徑:/data/data/<package_name>/shared_prefs 資料夾下
2.Internal Storage:
  • 資料儲存在內部儲存空間,一般使用者權限無法任意存取該檔案
  • 檔案路徑:/data/data/<package_name> 資料夾下
3.External Storage:
  • 資料儲存到外部儲存空間,一般使用者有權限任意存取該檔案
  • 檔案路徑:/storage/sdcard0/ 資料夾下
4.SQLite Databases:
  • 資料儲存到 SQLite 資料庫中
  • 檔案路徑:/data/data/<package_name>/databases 資料夾下


0x01 常見弱點風險

1.Shared Preferences:
  • 風險位置:getSharedPreferences、getPreferences
  • 帳號密碼等敏感性資料以明文方式儲存
  • 賦予 SharedPreferences 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險)
  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案

2.Internal Storage:
  • 風險位置:openFileOutput、getFilesDir、getCacheDir
  • 帳號密碼等敏感性資料以明文方式儲存
  • 賦予儲存在本機內部儲存空間的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >=17無風險)
  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案

3.External Storage:
  • 風險位置:getExternalFilesDir、getExternalCacheDir、getExternalFilesDirs、getExternalCacheDirs、getExternalStorageDirectory、getExternalStoragePublicDirectory
  • 帳號密碼等敏感性資料以明文方式儲存

4.SQLite Databases:
  • 風險位置:openOrCreateDatabase
  • 帳號密碼等敏感性資料以明文方式儲存
  • 賦予儲存為 SQLite db 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >=17無風險)

0x02 弱點檢測方式

1.Shared Preferences 弱點檢測方式:

未加殼

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)將 apk 反組譯回 smali code,追 「getSharedPreferences」、「getPreferences」,檢查是否未加密儲存敏感性資料。

  • 賦予 SharedPreferences 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則檢查 smali code 是否存在「getSharedPreferences」或「getPreferences」字串,並檢查其後是否使用「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」權限。

  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案:
(1)將 apk 反組譯,檢查 AndroidManifest.xml 是否宣告「android:sharedUserId」。

已加殼且脫不掉

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)手動操作完app所有功能,包含資料輸入等。
(2)adb shell 進入手機後 su 提權,將 /data/data/<package_name>/shared_prefs/ 下的檔案取出,並檢查該檔案是否以明文儲存敏感性資料。

  • 賦予 SharedPreferences 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則透過 ls -all 方式,檢查 /data/data/<package_name>/shared_prefs/ 下的一般使用者檔案權限狀態是否有 r 或 w。

  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案:
方法與未加殼相同。


2.Internal Storage 弱點檢測方式:

未加殼

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)將 apk 反組譯回 smali code,追 「openFileOutput」、「getFilesDir」、「getCacheDir」,檢查是否未加密儲存敏感性資料。

  • 賦予儲存在本機內部儲存空間的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則檢查 smali code 是否存在「openFileOutput」或「getFilesDir」或「getCacheDir」字串,並檢查其後是否使用「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」權限。

  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案:
(1)將 apk 反組譯,檢查 AndroidManifest.xml 是否宣告「android:sharedUserId」。

已加殼且脫不掉

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)手動操作完app所有功能,包含資料輸入等。
(2)adb shell 進入手機後 su 提權,將 /data/data/<package_name>/ 下的檔案取出,並檢查所有檔案是否以明文儲存敏感性資料。同時建議搭配 hook 檢查是否未在其他資料夾中儲存檔案。

  • 賦予儲存在本機內部儲存空間的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則透過 ls -all 方式,檢查 /data/data/<package_name>/ 下的一般使用者檔案權限狀態是否有 r 或 w。

  • AndroidManifest.xml 中宣告「android:sharedUserId」供其他使用相同 sharedUserId 的 App 存取其相關檔案:
方法與未加殼相同。


3.External Storage 弱點檢測方式:

未加殼

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)將 apk 反組譯回 smali code,追 「getExternalFilesDir」、「getExternalCacheDir」、「getExternalFilesDirs」、「getExternalCacheDirs」、「getExternalStorageDirectory」、「getExternalStoragePublicDirectory」,檢查是否未加密儲存敏感性資料。

已加殼且脫不掉

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)手動操作完app所有功能,包含資料輸入等。
(2)adb shell echo $EXTERNAL_STORAGE 取得外部儲存空間路徑,並將該路徑下的所有檔案取出,檢查是否以明文儲存敏感性資料。


4.SQLite Databases 弱點檢測方式:

未加殼

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)將 apk 反組譯回 smali code,追 「openOrCreateDatabase」檢查是否未加密儲存敏感性資料。

  • 賦予儲存為 SQLite db 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則檢查 smali code 是否存在「openOrCreateDatabase」字串,並檢查其後是否使用「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」權限。

已加殼且脫不掉

  • 帳號密碼等敏感性資料以明文方式儲存:
(1)手動操作完app所有功能,包含資料輸入等。
(2)adb shell 進入手機後 su 提權,將 /data/data/<package_name>/databases/下的檔案取出,並檢查該檔案是否以明文儲存敏感性資料。

  • 賦予儲存為 SQLite db 的檔案 MODE_WORLD_READABLE 或 MODE_WORLD_WRITABLE 權限(API Level >= 17 無風險):
(1)將 apk 反組譯,檢查 「AndroidManifest.xml」 宣告的「minSdkVersion」是否 >=17,若是,則不用檢查 「MODE_WORLD_READABLE」或「MODE_WORLD_WRITABLE」 權限;若否,則透過 ls -all 方式,檢查 /data/data/<package_name>/databases/ 下的一般使用者檔案權限狀態是否有 r 或 w。


0x03參考資料:

(1)owasp-mstg:0x01a_OMTG-DATAST_Android.md
(2)Android本地數據存儲:Internal Storage安全風險淺析
(3)Android本地數據存儲:Shared Preferences安全風險淺析
(4)Android Database配置模式安全風險淺析
(5)Android sharedUserId研究記錄

沒有留言:

張貼留言