AndroidManifest.xml中含蓋的安全問題詳解
0x00 關於AndroidManifest.xml
AndroidManifest.xml 是每個android程式中必須的檔案。它位於整個專案的根目錄,Manifest檔案提供有關應用程式到Android系統的基本資訊,系統必須具有該資訊才能執行任何應用程式的程式碼。換句話說APP是跑在Android系統上,既然要跑在其上,就必須提供資訊給Android System,這些資訊就存在AndroidManifest中。AndroidManifest.xml
存放在 app/src/main/ 目錄下。在反編譯APK檔案後,其檔案是以亂碼格式存在,需要進行轉換才能正常檢視。
AndroidManifest.xml的主要功能
- 命名應用程式Java包,軟體包名稱作為應用程式的唯一識別符號;
- 描述了應用程式的元件,其中包括構成應用程式的Activity,Service,Broadcast Receiver和Content Provider;它還命名實現每個元件併發布其功能的類,例如Intent可以處理的訊息。這些宣告通知Android系統的元件及其可以啟動的條件;
- 決定哪些processes主持application;
- 宣告這個App有哪些許可權,它宣告應用程式必須擁有的許可權才能訪問API的受保護部分並與其他應用程式互動。它還宣告其他人為了與應用程式的元件互動而需要的許可權; 5.它列出了Instrumentation在應用程式執行時提供概要分析和其他資訊的類。這些宣告僅在應用程式正在開發中才會存在,並在應用程式釋出之前被刪除; 6.它聲明瞭應用程式需要的最低級別的Android API; 7.它列出了應用程式必須連結的庫。
<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mwr.example.sieve"> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> <permission android:label="Allows reading of the Key in Sieve" android:name="com.mwr.example.sieve.READ_KEYS" android:protectionLevel="dangerous"/> <permission android:label="Allows editing of the Key in Sieve" android:name="com.mwr.example.sieve.WRITE_KEYS" android:protectionLevel="dangerous"/> <application android:allowBackup="true" android:debuggable="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:exported="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_file_select" android:name=".FileSelectActivity"/> <activity android:excludeFromRecents="true" android:label="@string/app_name" android:launchMode="singleTask" android:name=".MainLoginActivity" android:windowSoftInputMode="adjustResize|stateVisible"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:exported="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_pwlist" android:name=".PWList"/> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_settings" android:name=".SettingsActivity"/> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_add_entry" android:name=".AddEntryActivity"/> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_short_login" android:name=".ShortLoginActivity"/> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_welcome" android:name=".WelcomeActivity"/> <activity android:clearTaskOnLaunch="true" android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:label="@string/title_activity_pin" android:name=".PINActivity"/> <service android:exported="true" android:name=".AuthService" android:process=":remote"/> <service android:exported="true" android:name=".CryptoService" android:process=":remote"/> <provider android:authorities="com.mwr.example.sieve.DBContentProvider" android:exported="true" android:multiprocess="true" android:name=".DBContentProvider"> <path-permission android:path="/Keys" android:readPermission="com.mwr.example.sieve.READ_KEYS" android:writePermission="com.mwr.example.sieve.WRITE_KEYS"/> </provider> <provider android:authorities="com.mwr.example.sieve.FileBackupProvider" android:exported="true" android:multiprocess="true" android:name=".FileBackupProvider"/> </application> </manifest>
0x01 AndroidManifest.xml風險點分析
1、allowBackup設定風險
Android API Level 8 (Android 2.1)及其以上Android系統提供了為應用程式資料的備份和恢復功能,此功能的開關決定於該應用程式中 AndroidManifest.xml 檔案中的 allowBackup 屬性值,其屬性值預設是 true。當allowBackup的屬性值沒有顯示設定為false時,攻擊者可通過 adb backup 和 adb restore 來進行對應用資料的備份和恢復,從而可能獲取明文儲存的使用者的敏感資訊。
android:allowBackup=["true" | "false"]
$ adb backup -nosystem -noshared -apk -f com.example.demo $ adb restore com.example.demo
- -nosystem表示不備份系統應用
- -noshared表示不備份應用儲存在SD中的資料
- -apk表示備份應用APK安裝包
- -f表示備份的.ab檔案路徑和檔名,最後是要備份應用的packageName
- restore是恢復備份的資料
2、debuggable設定風險
該屬性用於指定應用程式是否能夠被除錯,即使是以使用者模式執行在裝置上的時候,如果設定為true,則可以被除錯;但是現在Android版本均預設debuggable的屬性值為false,所以建議使用預設配置。
android:debuggable=["true" | "false"]
3、元件匯出風險
四大元件
- Activity
- Broadcast Receive
- Service
- Content Provider
可匯出的元件能被第三方APP任意呼叫,導致敏感資訊洩露,並可能被利用於繞過認證、惡意程式碼注入、sql注入、拒絕服務等攻擊;
Activity中exported的預設值
- 沒有intent filter時,預設為false
- 有intent filter時,預設為true
而intent filter標籤代表是主Activity,而每個APP都會有一個主Activity,所以當應用的Activity不必要匯出時,或者配置了intent filter標籤,建議顯示設定android:exported="false"。如果元件必須要匯出給其他應用使用,建議對元件進行許可權控制。
Broadcast Receive和Service的預設值都跟Activity的一樣。
Content Provider中exported的預設值
當minSdkVersion或者targetSdkVersion小於16時,預設為true 大於17時,預設為false
4、自定義許可權風險
在Android系統的安全模型中,應用程式在預設的情況下不可以執行任何對其他應用程式、系統或使用者帶來負面影響的操作。如果應用需要執行某些操作,就需要宣告使用這個操作對應的許可權,也就是在AndroidManifest.xml檔案中新增<uses-permission>標記,當然也可以自定義屬於自己的permission。但是如果許可權控制不當,那麼就可能導致各種越權等安全問題。
<uses-permission android:name="android.permission.INTERNET"/> <permission android:label="Allows reading of the Key in Sieve" android:name="com.mwr.example.sieve.READ_KEYS" android:protectionLevel="dangerous"/> android:protectionLevel=["normal" | "dangerous" | "signature" | "signatureOrSystem"]
- normal:這是最低風險的許可權,如果應用聲明瞭此許可權,系統直接預設該應用有此許可權,也不會提示安裝應用的使用者授權;
- dangerous:系統在安裝此類許可權宣告的應用時會提示使用者,但是所有APP都能訪問和共享此許可權;
- signature:這種許可權級別叫做高階許可權或者系統許可權,只有當發請求的應用和接收此請求的應用使用同一簽名檔案,並且聲明瞭該許可權才會授權,並且是預設授權,不會提示使用者授權
- signatureOrSystem:這種許可權應該儘量避免使用,偏向系統級
0x02 AndroidManifest.xml結構
<?xmlversion="1.0"encoding="utf-8"?> <manifest> <application> <activity> <intent-filter> <action/> <category/> </intent-filter> </activity> <activity-alias> <intent-filter></intent-filter> <meta-data/> </activity-alias> <service> <intent-filter></intent-filter> <meta-data/> </service> <receiver> <intent-filter></intent-filter> <meta-data/> </receiver> <provider> <grant-uri-permission/> <meta-data/> </provider> <uses-library/> </application> <uses-permission/> <permission/> <permission-tree/> <permission-group/> <instrumentation/> <uses-sdk/> <uses-configuration/> <uses-feature/> <supports-screens/> </manifest>
0x03 AndroidManifest.xml分節介紹
1、manifest
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.woody.test" android:sharedUserId="string" android:sharedUserLabel="string resource" android:versionCode="integer" android:versionName="string" android:installLocation=["auto" | "internalOnly" | "preferExternal"] > </manifest>
2、application
<application android:allowClearUserData=["true" | "false"] android:allowTaskReparenting=["true" | "false"] android:backupAgent="string" android:debuggable=["true" | "false"] android:description="string resource" android:enabled=["true" | "false"] android:hasCode=["true" | "false"] android:icon="drawable resource" android:killAfterRestore=["true" | "false"] android:label="string resource" android:manageSpaceActivity="string" android:name="string" android:permission="string" android:persistent=["true" | "false"] android:process="string" android:restoreAnyVersion=["true" | "false"] android:taskAffinity="string" android:theme="resource or theme" > </application>
3、activity
<activity android:allowTaskReparenting=["true" | "false"] android:alwaysRetainTaskState=["true" | "false"] android:clearTaskOnLaunch=["true" | "false"] android:configChanges=["mcc","mnc","locale","touchscreen","keyboard","keyboardHidden","navigation","orientation","screenLayout","fontScale","uiMode"] android:enabled=["true" | "false"] android:excludeFromRecents=["true" | "false"] android:exported=["true" | "false"] android:finishOnTaskLaunch=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:launchMode=["multiple" | "singleTop" | "singleTask" | "singleInstance"] android:multiprocess=["true" | "false"] android:name="string" android:noHistory=["true" | "false"] android:permission="string" android:process="string" android:screenOrientation=["unspecified" | "user" | "behind" | "landscape" | "portrait" | "sensor" | "nosensor"] android:stateNotNeeded=["true" | "false"] android:taskAffinity="string" android:theme="resource or theme" android:windowSoftInputMode=["stateUnspecified","stateUnchanged","stateHidden","stateAlwaysHidden","stateVisible","stateAlwaysVisible","adjustUnspecified","adjustResize","adjustPan"] > </activity>
4、intent-filter
<intent-filter android:icon="drawable resource" android:label="string resource" android:priority="integer" > <action /> <category /> <data /> </intent-filter>
5、meta-data
<meta-data android:name="string" android:resource="resource specification" android:value="string"/>
6、activity-alias
<activity-alias android:enabled=["true" | "false"] android:exported=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:targetActivity="string"> <intent-filter/> <meta-data/> </activity-alias>
7、service
<service android:enabled=["true" | "false"] android:exported[="true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:permission="string" android:process="string"> </service>
8、receiver
9、provider
<provider android:authorities="list" android:enabled=["true" | "false"] android:exported=["true" | "false"] android:grantUriPermissions=["true" | "false"] android:icon="drawable resource" android:initOrder="integer" android:label="string resource" android:multiprocess=["true" | "false"] android:name="string" android:permission="string" android:process="string" android:readPermission="string" android:syncable=["true" | "false"] android:writePermission="string"> <grant-uri-permission/> <meta-data/> </provider>
10、uses-library 11、supports-screens
<supports-screens android:smallScreens=["true" | "false"] android:normalScreens=["true" | "false"] android:largeScreens=["true" | "false"] android:anyDensity=["true" | "false"] />
12、uses-configuration和uses-feature
<uses-configuration android:reqFiveWayNav=["true" | "false"] android:reqHardKeyboard=["true" | "false"] android:reqKeyboardType=["undefined" | "nokeys" | "qwerty" | "twelvekey"] android:reqNavigation=["undefined" | "nonav" | "dpad" | "trackball" | "wheel"] android:reqTouchScreen=["undefined" | "notouch" | "stylus" | "finger"] /> <uses-feature android:glEsVersion="integer" android:name="string" android:required=["true" | "false"] />
13、uses-sdk
<uses-sdk android:minSdkVersion="integer" android:targetSdkVersion="integer" android:maxSdkVersion="integer"/>
14、instrumentation
<instrumentation android:functionalTest=["true" | "false"] android:handleProfiling=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:name="string" android:targetPackage="string"/>
15、<permission>、<uses-permission>、<permission-tree />、<permission-group />區別
最常用的當屬<uses-permission>,
當我們需要獲取某個許可權的時候就必須在我們的manifest檔案中宣告,此<uses-permission>
與<application>同級,具體許可權列表請看此處
通常情況下我們不需要為自己的應用程式宣告某個許可權,除非你提供了供其他應用程式呼叫的程式碼或者資料。這個時候你才需要使用<permission> 這個標籤。很顯然這個標籤可以讓我們宣告自己的許可權。比如:
<permission android:name="com.teleca.project.MY_SECURITY" . . . />
那麼在activity中就可以宣告該自定義許可權了,如:
<application . . .> <activity android:name="XXX" . . . > android:permission="com.teleca.project.MY_SECURITY"> </activity> </application>
當然自己宣告的permission也不能隨意的使用,還是需要使用<uses-permission>
來宣告你需要該許可權<permission-group>
就是宣告一個標籤,該標籤代表了一組permissions,而<permission-tree>
是為一組permissions聲明瞭一個namespace。這兩個標籤可以看之前的系列文章。
到此這篇關於AndroidManifest.xml中含蓋的安全問題的文章就介紹到這了,更多相關AndroidManifest.xml中含蓋的安全問題內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!