mirror of
https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
synced 2026-10-12 02:06:59 +00:00
[HOTFIX] bs4 malformed xml parsing + xml namespace detection (#2248)
* Use BeautifulSoup4 to prettify malformed XML * Detect non standard XML namespace in AndroidManifest.xml (Fixes : https://github.com/MobSF/Mobile-Security-Framework-MobSF/issues/2198) * Updated android permissions list * Updated android permission update check script
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
# along with Androguard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# frameworks/base/core/res/AndroidManifest.xml
|
||||
|
||||
# This list is also updated periodically with scripts/update_android_permissions.py
|
||||
# ######################################### PERMISSIONS ###################
|
||||
# flake8: noqa
|
||||
DVM_PERMISSIONS = {
|
||||
@@ -244,6 +246,142 @@ DVM_PERMISSIONS = {
|
||||
'REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE': ['normal', '', 'Allows an application to subscribe to notifications about the presence status change of their associated companion device.'],
|
||||
'SCHEDULE_EXACT_ALARM': ['normal', '', 'Allows an app to use exact alarm scheduling APIs to perform timing sensitive background work.'],
|
||||
'USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER': ['signature', '', 'Allows to read device identifiers and use ICC based authentication like EAP-AKA. Often required in authentication to access the carrier\'s server and manage services of the subscriber.'],
|
||||
'ACCESS_BLOBS_ACROSS_USERS': ['normal', '', 'Allows an application to access data blobs across users.'],
|
||||
'BIND_CREDENTIAL_PROVIDER_SERVICE': ['signature', '', 'Must be required by a CredentialProviderService to ensure that only the system can bind to it.'],
|
||||
'BIND_TV_INTERACTIVE_APP': ['signature', '', 'Must be required by a TvInteractiveAppService to ensure that only the system can bind to it.'],
|
||||
'BLUETOOTH_ADVERTISE': ['dangerous', '', 'Required to be able to advertise to nearby Bluetooth devices.'],
|
||||
'BLUETOOTH_CONNECT': ['dangerous', '', 'Required to be able to connect to paired Bluetooth devices.'],
|
||||
'BLUETOOTH_SCAN': ['dangerous', '', 'Required to be able to discover and pair nearby Bluetooth devices.'],
|
||||
'BODY_SENSORS_BACKGROUND': ['dangerous', '', "Allows an application to access data from sensors that the user uses to measure what is happening inside their body, such as heart rate. If you're requesting this permission, you must also request BODY_SENSORS . Requesting this permission by itself doesn't give you Body sensors access."],
|
||||
'CONFIGURE_WIFI_DISPLAY': ['normal', '', 'Allows an application to configure and connect to Wifi displays'],
|
||||
'CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS': ['normal', '', 'Allows a browser to invoke the set of query apis to get metadata about credential candidates prepared during the CredentialManager.prepareGetCredential API.'],
|
||||
'CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS': ['normal', '', 'Allows specifying candidate credential providers to be queried in Credential Manager get flows, or to be preferred as a default in the Credential Manager create flows.'],
|
||||
'CREDENTIAL_MANAGER_SET_ORIGIN': ['normal', '', 'Allows a browser to invoke credential manager APIs on behalf of another RP.'],
|
||||
'DELIVER_COMPANION_MESSAGES': ['normal', '', 'Allows an application to deliver companion messages to system'],
|
||||
'DETECT_SCREEN_CAPTURE': ['normal', '', 'Allows an application to get notified when a screen capture of its windows is attempted.'],
|
||||
'ENFORCE_UPDATE_OWNERSHIP': ['normal', '', 'Allows an application to indicate via PackageInstaller.SessionParams.setRequestUpdateOwnership(boolean) that it has the intention of becoming the update owner.'],
|
||||
'EXECUTE_APP_ACTION': ['internal', '', 'Allows an assistive application to perform actions on behalf of users inside of applications.'],
|
||||
'FOREGROUND_SERVICE_CAMERA': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "camera".'],
|
||||
'FOREGROUND_SERVICE_CONNECTED_DEVICE': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "connectedDevice".'],
|
||||
'FOREGROUND_SERVICE_DATA_SYNC': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "dataSync".'],
|
||||
'FOREGROUND_SERVICE_HEALTH': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "health".'],
|
||||
'FOREGROUND_SERVICE_LOCATION': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "location".'],
|
||||
'FOREGROUND_SERVICE_MEDIA_PLAYBACK': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "mediaPlayback".'],
|
||||
'FOREGROUND_SERVICE_MEDIA_PROJECTION': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "mediaProjection".'],
|
||||
'FOREGROUND_SERVICE_MICROPHONE': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "microphone".'],
|
||||
'FOREGROUND_SERVICE_PHONE_CALL': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "phoneCall".'],
|
||||
'FOREGROUND_SERVICE_REMOTE_MESSAGING': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "remoteMessaging".'],
|
||||
'FOREGROUND_SERVICE_SPECIAL_USE': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "specialUse".'],
|
||||
'FOREGROUND_SERVICE_SYSTEM_EXEMPTED': ['normal', '', 'Allows a regular application to use Service.startForeground with the type "systemExempted". Apps are allowed to use this type only in the use cases listed in ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED .'],
|
||||
'LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE': ['internal', '', 'Allows an application to capture screen content to perform a screenshot using the intent action Intent.ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE .'],
|
||||
'LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK': ['normal', '', 'An application needs this permission for Settings.ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY to show its Activity embedded in Settings app.'],
|
||||
'MANAGE_DEVICE_LOCK_STATE': ['internal', '', 'Allows financed device kiosk apps to perform actions on the Device Lock service'],
|
||||
'MANAGE_DEVICE_POLICY_ACCESSIBILITY': ['normal', '', 'Allows an application to manage policy related to accessibility. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT': ['normal', '', 'Allows an application to set policy related to account management. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_ACROSS_USERS': ['normal', '', 'Allows an application to set device policies outside the current user that are required for securing device ownership without accessing user data. Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_* permissions across all users on the device provided they do not grant access to user data.'],
|
||||
'MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL': ['normal', '', 'Allows an application to set device policies outside the current user. Fuller form of MANAGE_DEVICE_POLICY_ACROSS_USERS that removes the restriction on accessing user data. Holding this permission allows the use of any other held MANAGE_DEVICE_POLICY_* permissions across all users on the device. Constant Value: "android.permission.MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL"'],
|
||||
'MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL': ['normal', '', 'Allows an application to set device policies outside the current user that are critical for securing data within the current user. Holding this permission allows the use of other held MANAGE_DEVICE_POLICY_* permissions across all users on the device provided they are required for securing data within the current user.'],
|
||||
'MANAGE_DEVICE_POLICY_AIRPLANE_MODE': ['normal', '', 'Allows an application to set policy related to airplane mode. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_APPS_CONTROL': ['normal', '', 'Allows an application to manage policy regarding modifying applications. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_APP_RESTRICTIONS': ['normal', '', 'Allows an application to manage application restrictions. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_APP_USER_DATA': ['normal', '', 'Allows an application to manage policy related to application user data. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_AUDIO_OUTPUT': ['normal', '', 'Allows an application to set policy related to audio output. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_AUTOFILL': ['normal', '', 'Allows an application to set policy related to autofill. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_BACKUP_SERVICE': ['normal', '', 'Allows an application to manage backup service policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_BLUETOOTH': ['normal', '', 'Allows an application to set policy related to bluetooth. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_BUGREPORT': ['normal', '', 'Allows an application to request bugreports with user consent. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_CALLS': ['normal', '', 'Allows an application to manage calling policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_CAMERA': ['normal', '', "Allows an application to set policy related to restricting a user's ability to use or enable and disable the camera. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user."],
|
||||
'MANAGE_DEVICE_POLICY_CERTIFICATES': ['normal', '', 'Allows an application to set policy related to certificates. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_COMMON_CRITERIA_MODE': ['normal', '', 'Allows an application to manage policy related to common criteria mode. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_DEBUGGING_FEATURES': ['normal', '', 'Allows an application to manage debugging features policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_DEFAULT_SMS': ['normal', '', 'Allows an application to set policy related to the default sms application. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_DEVICE_IDENTIFIERS': ['normal', '', 'Allows an application to manage policy related to device identifiers.'],
|
||||
'MANAGE_DEVICE_POLICY_DISPLAY': ['normal', '', 'Allows an application to set policy related to the display. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_FACTORY_RESET': ['normal', '', 'Allows an application to set policy related to factory reset. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_FUN': ['normal', '', 'Allows an application to set policy related to fun. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_INPUT_METHODS': ['normal', '', 'Allows an application to set policy related to input methods. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_INSTALL_UNKNOWN_SOURCES': ['normal', '', 'Allows an application to manage installing from unknown sources policy. MANAGE_SECURITY_CRITICAL_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_KEEP_UNINSTALLED_PACKAGES': ['normal', '', 'Allows an application to set policy related to keeping uninstalled packages. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_KEYGUARD': ['normal', '', 'Allows an application to manage policy related to keyguard. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_LOCALE': ['normal', '', 'Allows an application to set policy related to locale. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_LOCATION': ['normal', '', 'Allows an application to set policy related to location. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_LOCK': ['normal', '', 'Allows an application to lock a profile or the device with the appropriate cross-user permission. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS': ['normal', '', 'Allows an application to set policy related to lock credentials. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_SECURITY_CRITICAL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_LOCK_TASK': ['normal', '', 'Allows an application to manage lock task policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_METERED_DATA': ['normal', '', 'Allows an application to manage policy related to metered data. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_MICROPHONE': ['normal', '', "Allows an application to set policy related to restricting a user's ability to use or enable and disable the microphone. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user."],
|
||||
'MANAGE_DEVICE_POLICY_MOBILE_NETWORK': ['normal', '', 'Allows an application to set policy related to mobile networks. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_MODIFY_USERS': ['normal', '', 'Allows an application to manage policy preventing users from modifying users. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user'],
|
||||
'MANAGE_DEVICE_POLICY_MTE': ['normal', '', 'Allows an application to manage policy related to the Memory Tagging Extension (MTE).'],
|
||||
'MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION': ['normal', '', 'Allows an application to set policy related to nearby communications (e.g.Beam and nearby streaming). Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_NETWORK_LOGGING': ['normal', '', 'Allows an application to set policy related to network logging. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY': ['normal', '', 'Allows an application to manage the identity of the managing organization. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_OVERRIDE_APN': ['normal', '', 'Allows an application to set policy related to override APNs. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PACKAGE_STATE': ['normal', '', 'Allows an application to set policy related to hiding and suspending packages. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PHYSICAL_MEDIA': ['normal', '', 'Allows an application to set policy related to physical media. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PRINTING': ['normal', '', 'Allows an application to set policy related to printing. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PRIVATE_DNS': ['normal', '', 'Allows an application to set policy related to private DNS. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PROFILES': ['normal', '', 'Allows an application to set policy related to profiles. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PROFILE_INTERACTION': ['normal', '', 'Allows an application to set policy related to interacting with profiles (e.g.Disallowing cross-profile copy and paste). Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_PROXY': ['normal', '', 'Allows an application to set a network-independent global HTTP proxy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_QUERY_SYSTEM_UPDATES': ['normal', '', 'Allows an application query system updates. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_RESET_PASSWORD': ['normal', '', 'Allows an application to force set a new device unlock password or a managed profile challenge on current user. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_RESTRICT_PRIVATE_DNS': ['normal', '', 'Allows an application to set policy related to restricting the user from configuring private DNS. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS': ['normal', '', 'Allows an application to set the grant state of runtime permissions on packages. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_RUN_IN_BACKGROUND': ['normal', '', 'Allows an application to set policy related to users running in the background. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SAFE_BOOT': ['normal', '', 'Allows an application to manage safe boot policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SCREEN_CAPTURE': ['normal', '', 'Allows an application to set policy related to screen capture. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SCREEN_CONTENT': ['normal', '', 'Allows an application to set policy related to the usage of the contents of the screen. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SECURITY_LOGGING': ['normal', '', 'Allows an application to set policy related to security logging. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SETTINGS': ['normal', '', 'Allows an application to set policy related to settings. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SMS': ['normal', '', 'Allows an application to set policy related to sms. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_STATUS_BAR': ['normal', '', 'Allows an application to set policy related to the status bar.'],
|
||||
'MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE': ['normal', '', 'Allows an application to set support messages for when a user action is affected by an active policy. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SUSPEND_PERSONAL_APPS': ['normal', '', 'Allows an application to set policy related to suspending personal apps. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SYSTEM_APPS': ['normal', '', 'Allows an application to manage policy related to system apps. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS': ['normal', '', 'Allows an application to set policy related to system dialogs. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_SYSTEM_UPDATES': ['normal', '', 'Allows an application to set policy related to system updates. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_TIME': ['normal', '', 'Allows an application to manage device policy relating to time. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_USB_DATA_SIGNALLING': ['normal', '', 'Allows an application to set policy related to usb data signalling.'],
|
||||
'MANAGE_DEVICE_POLICY_USB_FILE_TRANSFER': ['normal', '', 'Allows an application to set policy related to usb file transfers. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_USERS': ['normal', '', 'Allows an application to set policy related to users. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_VPN': ['normal', '', 'Allows an application to set policy related to VPNs. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_WALLPAPER': ['normal', '', 'Allows an application to set policy related to the wallpaper. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_WIFI': ['normal', '', 'Allows an application to set policy related to Wifi. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_WINDOWS': ['normal', '', 'Allows an application to set policy related to windows. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS_FULL is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_DEVICE_POLICY_WIPE_DATA': ['normal', '', 'Allows an application to manage policy related to wiping data. Manifest.permission#MANAGE_DEVICE_POLICY_ACROSS_USERS is required to call APIs protected by this permission on users different to the calling user.'],
|
||||
'MANAGE_MEDIA': ['signature', '', 'Allows an application to modify and delete media files on this device or any connected storage device without user confirmation. Applications must already be granted the READ_EXTERNAL_STORAGE or MANAGE_EXTERNAL_STORAGE } permissions for this permission to take effect.'],
|
||||
'MANAGE_WIFI_INTERFACES': ['normal', '', 'Allows applications to get notified when a Wi-Fi interface request cannot be satisfied without tearing down one or more other interfaces, and provide a decision whether to approve the request or reject it. Not for use by third-party applications.'],
|
||||
'MANAGE_WIFI_NETWORK_SELECTION': ['normal', '', 'This permission is used to let OEMs grant their trusted app access to a subset of privileged wifi APIs to improve wifi performance. Allows applications to manage Wi-Fi network selection related features such as enable or disable global auto-join, modify connectivity scan intervals, and approve Wi-Fi Direct connections. Not for use by third-party applications.'],
|
||||
'NEARBY_WIFI_DEVICES': ['dangerous', '', 'Required to be able to advertise and connect to nearby devices via Wi-Fi.'],
|
||||
'OVERRIDE_WIFI_CONFIG': ['normal', '', 'Allows an application to modify any wifi configuration, even if created by another application. Once reconfigured the original creator cannot make any further modifications. Not for use by third-party applications.'],
|
||||
'POST_NOTIFICATIONS': ['dangerous', '', 'Allows an app to post notifications'],
|
||||
'PROVIDE_OWN_AUTOFILL_SUGGESTIONS': ['internal', '', 'Allows an application to display its suggestions using the autofill framework.'],
|
||||
'PROVIDE_REMOTE_CREDENTIALS': ['signature', '', 'Allows an application to be able to store and retrieve credentials from a remote device.'],
|
||||
'READ_ASSISTANT_APP_SEARCH_DATA': ['normal', '', "Allows an application to query over global data in AppSearch that's visible to the ASSISTANT role."],
|
||||
'READ_BASIC_PHONE_STATE': ['normal', '', 'Allows read only access to phone state with a non dangerous permission, including the information like cellular network type, software version.'],
|
||||
'READ_HOME_APP_SEARCH_DATA': ['normal', '', "Allows an application to query over global data in AppSearch that's visible to the HOME role."],
|
||||
'READ_MEDIA_AUDIO': ['dangerous', '', 'Allows an application to read audio files from external storage.'],
|
||||
'READ_MEDIA_IMAGES': ['dangerous', '', 'Allows an application to read image files from external storage.'],
|
||||
'READ_MEDIA_VIDEO': ['dangerous', '', 'Allows an application to read video files from external storage.'],
|
||||
'READ_MEDIA_VISUAL_USER_SELECTED': ['dangerous', '', 'Allows an application to read image or video files from external storage that a user has selected via the permission prompt photo picker. Apps can check this permission to verify that a user has decided to use the photo picker, instead of granting access to READ_MEDIA_IMAGES or READ_MEDIA_VIDEO . It does not prevent apps from accessing the standard photo picker manually. This permission should be requested alongside READ_MEDIA_IMAGES and/or READ_MEDIA_VIDEO , depending on which type of media is desired.'],
|
||||
'READ_NEARBY_STREAMING_POLICY': ['normal', '', 'Allows an application to read nearby streaming policy. The policy controls whether to allow the device to stream its notifications and apps to nearby devices. Applications that are not the device owner will need this permission to call DevicePolicyManager.getNearbyNotificationStreamingPolicy() or DevicePolicyManager.getNearbyAppStreamingPolicy() .'],
|
||||
'REQUEST_COMPANION_PROFILE_APP_STREAMING': ['normal', '', 'Allows application to request to be associated with a virtual display capable of streaming Android applications ( AssociationRequest.DEVICE_PROFILE_APP_STREAMING ) by CompanionDeviceManager . Not for use by third-party applications.'],
|
||||
'REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION': ['normal', '', 'Allows application to request to be associated with a vehicle head unit capable of automotive projection ( AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION ) by CompanionDeviceManager . Not for use by third-party applications.'],
|
||||
'REQUEST_COMPANION_PROFILE_COMPUTER': ['normal', '', 'Allows application to request to be associated with a computer to share functionality and/or data with other devices, such as notifications, photos and media ( AssociationRequest.DEVICE_PROFILE_COMPUTER ) by CompanionDeviceManager . Not for use by third-party applications.'],
|
||||
'REQUEST_COMPANION_PROFILE_GLASSES': ['normal', '', 'Allows app to request to be associated with a device via CompanionDeviceManager as "glasses"'],
|
||||
'REQUEST_COMPANION_PROFILE_NEARBY_DEVICE_STREAMING': ['normal', '', 'Allows application to request to stream content from an Android host to a nearby device ( AssociationRequest.DEVICE_PROFILE_NEARBY_DEVICE_STREAMING ) by CompanionDeviceManager . Not for use by third-party applications.'],
|
||||
'REQUEST_COMPANION_SELF_MANAGED': ['normal', '', 'Allows an application to create a "self-managed" association.'],
|
||||
'REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND': ['normal', '', 'Allows a companion app to start a foreground service from the background.'],
|
||||
'RUN_USER_INITIATED_JOBS': ['normal', '', 'Allows applications to use the user-initiated jobs API. For more details see JobInfo.Builder.setUserInitiated(boolean) .'],
|
||||
'START_FOREGROUND_SERVICES_FROM_BACKGROUND': ['normal', '', "Allows an application to start foreground services from the background at any time. This permission is not for use by third-party applications , with the only exception being if the app is the default SMS app. Otherwise, it's only usable by privileged apps, app verifier app, and apps with any of the EMERGENCY or SYSTEM GALLERY roles."],
|
||||
'START_VIEW_APP_FEATURES': ['signature', '', 'Allows the holder to start the screen with a list of app features.'],
|
||||
'SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE': ['signature', '', 'Allows an application to subscribe to keyguard locked (i.e., showing) state.'],
|
||||
'TURN_SCREEN_ON': ['normal', '', 'Allows an app to turn on the screen on, e.g. with PowerManager.ACQUIRE_CAUSES_WAKEUP . Intended to only be used by home automation apps.'],
|
||||
'UPDATE_PACKAGES_WITHOUT_USER_ACTION': ['normal', '', 'Allows an application to indicate via PackageInstaller.SessionParams.setRequireUserAction(int) that user action should not be required for an app update.'],
|
||||
'USE_EXACT_ALARM': ['normal', '', 'Allows apps to use exact alarms just like with SCHEDULE_EXACT_ALARM but without needing to request this permission from the user. This is only intended for use by apps that rely on exact alarms for their core functionality. You should continue using SCHEDULE_EXACT_ALARM if your app needs exact alarms for a secondary feature that users may or may not use within your app. Keep in mind that this is a powerful permission and app stores may enforce policies to audit and review the use of this permission. Such audits may involve removal from the app store if the app is found to be misusing this permission. Apps need to target API Build.VERSION_CODES.TIRAMISU or above to be able to request this permission. Note that only one of USE_EXACT_ALARM or SCHEDULE_EXACT_ALARM should be requested on a device. If your app is already using SCHEDULE_EXACT_ALARM on older SDKs but needs USE_EXACT_ALARM on SDK 33 and above, then SCHEDULE_EXACT_ALARM should be declared with a max-sdk attribute, like: <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" android:maxSdkVersion="32" /> Apps that hold this permission, always stay in the WORKING_SET or lower standby bucket.Constant Value: "android.permission.USE_EXACT_ALARM"'],
|
||||
'UWB_RANGING': ['dangerous', '', 'Required to be able to range to devices using ultra-wideband.'],
|
||||
},
|
||||
|
||||
'SPECIAL_PERMISSIONS': {
|
||||
|
||||
@@ -24,8 +24,10 @@ from mobsf.StaticAnalyzer.views.android.app import (
|
||||
parse_apk,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_analysis import (
|
||||
get_manifest,
|
||||
manifest_analysis,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_utils import (
|
||||
get_manifest,
|
||||
manifest_data,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.strings import (
|
||||
@@ -77,17 +79,21 @@ def common_analysis(request, app_dic, rescan, api, analysis_type):
|
||||
apk = parse_apk(app_dic['app_path'])
|
||||
if analysis_type == 'aar':
|
||||
# AAR has manifest and sometimes certificate
|
||||
app_dic['manifest_file'], app_dic['parsed_xml'] = get_manifest(
|
||||
mani_file, ns, mani_xml = get_manifest(
|
||||
app_dic['app_path'],
|
||||
app_dic['app_dir'],
|
||||
app_dic['tools_dir'],
|
||||
'aar',
|
||||
)
|
||||
app_dic['manifest_file'] = mani_file
|
||||
app_dic['ns'] = ns
|
||||
app_dic['parsed_xml'] = mani_xml
|
||||
app_dic['mani'] = (
|
||||
f'../manifest_view/?md5={app_dic["md5"]}&type=aar')
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'])
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'], ns)
|
||||
man_an_dic = manifest_analysis(
|
||||
app_dic['parsed_xml'],
|
||||
ns,
|
||||
man_data_dic,
|
||||
'',
|
||||
app_dic['app_dir'],
|
||||
|
||||
@@ -2,208 +2,22 @@
|
||||
# flake8: noqa
|
||||
"""Module for android manifest analysis."""
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from xml.dom import minidom
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from mobsf.MobSF.utils import (
|
||||
find_java_binary,
|
||||
is_file_exists,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android import (
|
||||
android_manifest_desc,
|
||||
network_security,
|
||||
)
|
||||
|
||||
# pylint: disable=E0401
|
||||
from .dvm_permissions import DVM_PERMISSIONS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
ANDROID_4_2_LEVEL = 17
|
||||
ANDROID_5_0_LEVEL = 21
|
||||
ANDROID_8_0_LEVEL = 26
|
||||
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
|
||||
|
||||
def get_manifest(app_path, app_dir, tools_dir, typ):
|
||||
"""Get the manifest file."""
|
||||
try:
|
||||
manifest_file = get_manifest_file(
|
||||
app_dir,
|
||||
app_path,
|
||||
tools_dir,
|
||||
typ)
|
||||
mfile = Path(manifest_file)
|
||||
if mfile.exists():
|
||||
manifest = mfile.read_text('utf-8', 'ignore')
|
||||
else:
|
||||
manifest = ''
|
||||
try:
|
||||
logger.info('Parsing AndroidManifest.xml')
|
||||
manifest = minidom.parseString(manifest)
|
||||
except Exception:
|
||||
err = ('apktool failed to extract '
|
||||
'AndroidManifest.xml or parsing failed')
|
||||
logger.exception(err)
|
||||
manifest = minidom.parseString(
|
||||
(r'<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android='
|
||||
r'"http://schemas.android.com/apk/res/android" '
|
||||
r'android:versionCode="Failed" '
|
||||
r'android:versionName="Failed" package="Failed" '
|
||||
r'platformBuildVersionCode="Failed" '
|
||||
r'platformBuildVersionName="Failed XML Parsing" ></manifest>'))
|
||||
logger.warning('Using Fake XML to continue the Analysis')
|
||||
return manifest_file, manifest
|
||||
except Exception:
|
||||
logger.exception('Parsing Manifest file')
|
||||
|
||||
|
||||
def manifest_data(mfxml):
|
||||
"""Extract manifest data."""
|
||||
try:
|
||||
logger.info('Extracting Manifest Data')
|
||||
svc = []
|
||||
act = []
|
||||
brd = []
|
||||
cnp = []
|
||||
lib = []
|
||||
perm = []
|
||||
cat = []
|
||||
icons = []
|
||||
dvm_perm = {}
|
||||
package = ''
|
||||
minsdk = ''
|
||||
maxsdk = ''
|
||||
targetsdk = ''
|
||||
mainact = ''
|
||||
androidversioncode = ''
|
||||
androidversionname = ''
|
||||
applications = mfxml.getElementsByTagName('application')
|
||||
permissions = mfxml.getElementsByTagName('uses-permission')
|
||||
manifest = mfxml.getElementsByTagName('manifest')
|
||||
activities = mfxml.getElementsByTagName('activity')
|
||||
services = mfxml.getElementsByTagName('service')
|
||||
providers = mfxml.getElementsByTagName('provider')
|
||||
receivers = mfxml.getElementsByTagName('receiver')
|
||||
libs = mfxml.getElementsByTagName('uses-library')
|
||||
sdk = mfxml.getElementsByTagName('uses-sdk')
|
||||
categories = mfxml.getElementsByTagName('category')
|
||||
for node in sdk:
|
||||
minsdk = node.getAttribute('android:minSdkVersion')
|
||||
maxsdk = node.getAttribute('android:maxSdkVersion')
|
||||
# Esteve 08.08.2016 - begin - If android:targetSdkVersion
|
||||
# is not set, the default value is the one of the
|
||||
# android:minSdkVersiontargetsdk
|
||||
# =node.getAttribute('android:targetSdkVersion')
|
||||
if node.getAttribute('android:targetSdkVersion'):
|
||||
targetsdk = node.getAttribute('android:targetSdkVersion')
|
||||
else:
|
||||
targetsdk = node.getAttribute('android:minSdkVersion')
|
||||
# End
|
||||
for node in manifest:
|
||||
package = node.getAttribute('package')
|
||||
androidversioncode = node.getAttribute('android:versionCode')
|
||||
androidversionname = node.getAttribute('android:versionName')
|
||||
alt_main = ''
|
||||
for activity in activities:
|
||||
act_2 = activity.getAttribute('android:name')
|
||||
act.append(act_2)
|
||||
if not mainact:
|
||||
# ^ Some manifest has more than one MAIN, take only
|
||||
# the first occurrence.
|
||||
for sitem in activity.getElementsByTagName('action'):
|
||||
val = sitem.getAttribute('android:name')
|
||||
if val == 'android.intent.action.MAIN':
|
||||
mainact = activity.getAttribute('android:name')
|
||||
# Manifest has no MAIN, look for launch activity.
|
||||
for sitem in activity.getElementsByTagName('category'):
|
||||
val = sitem.getAttribute('android:name')
|
||||
if val == 'android.intent.category.LAUNCHER':
|
||||
alt_main = activity.getAttribute('android:name')
|
||||
if not mainact and alt_main:
|
||||
mainact = alt_main
|
||||
|
||||
for service in services:
|
||||
service_name = service.getAttribute('android:name')
|
||||
svc.append(service_name)
|
||||
|
||||
for provider in providers:
|
||||
provider_name = provider.getAttribute('android:name')
|
||||
cnp.append(provider_name)
|
||||
|
||||
for receiver in receivers:
|
||||
rec = receiver.getAttribute('android:name')
|
||||
brd.append(rec)
|
||||
|
||||
for _lib in libs:
|
||||
library = _lib.getAttribute('android:name')
|
||||
lib.append(library)
|
||||
|
||||
for category in categories:
|
||||
cat.append(category.getAttribute('android:name'))
|
||||
|
||||
for application in applications:
|
||||
try:
|
||||
icon_path = application.getAttribute('android:icon')
|
||||
icons.append(icon_path)
|
||||
except Exception:
|
||||
continue # No icon attribute?
|
||||
|
||||
android_permission_tags = ('com.google.', 'android.', 'com.google.')
|
||||
for permission in permissions:
|
||||
perm.append(permission.getAttribute('android:name'))
|
||||
for full_perm in perm:
|
||||
# For general android permissions
|
||||
prm = full_perm
|
||||
pos = full_perm.rfind('.')
|
||||
if pos != -1:
|
||||
prm = full_perm[pos + 1:]
|
||||
if not full_perm.startswith(android_permission_tags):
|
||||
prm = full_perm
|
||||
try:
|
||||
dvm_perm[full_perm] = DVM_PERMISSIONS[
|
||||
'MANIFEST_PERMISSION'][prm]
|
||||
except KeyError:
|
||||
# Handle Special Perms
|
||||
if DVM_PERMISSIONS['SPECIAL_PERMISSIONS'].get(full_perm):
|
||||
dvm_perm[full_perm] = DVM_PERMISSIONS[
|
||||
'SPECIAL_PERMISSIONS'][full_perm]
|
||||
else:
|
||||
dvm_perm[full_perm] = [
|
||||
'unknown',
|
||||
'Unknown permission',
|
||||
'Unknown permission from android reference',
|
||||
]
|
||||
|
||||
man_data_dic = {
|
||||
'services': svc,
|
||||
'activities': act,
|
||||
'receivers': brd,
|
||||
'providers': cnp,
|
||||
'libraries': lib,
|
||||
'categories': cat,
|
||||
'perm': dvm_perm,
|
||||
'packagename': package,
|
||||
'mainactivity': mainact,
|
||||
'min_sdk': minsdk,
|
||||
'max_sdk': maxsdk,
|
||||
'target_sdk': targetsdk,
|
||||
'androver': androidversioncode,
|
||||
'androvername': androidversionname,
|
||||
'icons': icons,
|
||||
}
|
||||
|
||||
return man_data_dic
|
||||
except Exception:
|
||||
logger.exception('Extracting Manifest Data')
|
||||
|
||||
|
||||
def get_browsable_activities(node):
|
||||
def get_browsable_activities(node, ns):
|
||||
"""Get Browsable Activities."""
|
||||
try:
|
||||
browse_dic = {}
|
||||
@@ -216,28 +30,28 @@ def get_browsable_activities(node):
|
||||
path_patterns = []
|
||||
catg = node.getElementsByTagName('category')
|
||||
for cat in catg:
|
||||
if cat.getAttribute('android:name') == 'android.intent.category.BROWSABLE':
|
||||
if cat.getAttribute(f'{ns}:name') == 'android.intent.category.BROWSABLE':
|
||||
data_tag = node.getElementsByTagName('data')
|
||||
for data in data_tag:
|
||||
scheme = data.getAttribute('android:scheme')
|
||||
scheme = data.getAttribute(f'{ns}:scheme')
|
||||
if scheme and scheme not in schemes:
|
||||
schemes.append(scheme)
|
||||
mime = data.getAttribute('android:mimeType')
|
||||
mime = data.getAttribute(f'{ns}:mimeType')
|
||||
if mime and mime not in mime_types:
|
||||
mime_types.append(mime)
|
||||
host = data.getAttribute('android:host')
|
||||
host = data.getAttribute(f'{ns}:host')
|
||||
if host and host not in hosts:
|
||||
hosts.append(host)
|
||||
port = data.getAttribute('android:port')
|
||||
port = data.getAttribute(f'{ns}:port')
|
||||
if port and port not in ports:
|
||||
ports.append(port)
|
||||
path = data.getAttribute('android:path')
|
||||
path = data.getAttribute(f'{ns}:path')
|
||||
if path and path not in paths:
|
||||
paths.append(path)
|
||||
path_prefix = data.getAttribute('android:pathPrefix')
|
||||
path_prefix = data.getAttribute(f'{ns}:pathPrefix')
|
||||
if path_prefix and path_prefix not in path_prefixs:
|
||||
path_prefixs.append(path_prefix)
|
||||
path_pattern = data.getAttribute('android:pathPattern')
|
||||
path_pattern = data.getAttribute(f'{ns}:pathPattern')
|
||||
if path_pattern and path_pattern not in path_patterns:
|
||||
path_patterns.append(path_pattern)
|
||||
schemes = [scheme + '://' for scheme in schemes]
|
||||
@@ -254,7 +68,7 @@ def get_browsable_activities(node):
|
||||
logger.exception('Getting Browsable Activities')
|
||||
|
||||
|
||||
def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
def manifest_analysis(mfxml, ns, man_data_dic, src_type, app_dir):
|
||||
"""Analyse manifest file."""
|
||||
# pylint: disable=C0301
|
||||
try:
|
||||
@@ -277,9 +91,9 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
debuggable = False
|
||||
# PERMISSION
|
||||
for permission in permissions:
|
||||
if permission.getAttribute('android:protectionLevel'):
|
||||
if permission.getAttribute(f'{ns}:protectionLevel'):
|
||||
protectionlevel = permission.getAttribute(
|
||||
'android:protectionLevel')
|
||||
f'{ns}:protectionLevel')
|
||||
if protectionlevel == '0x00000000':
|
||||
protectionlevel = 'normal'
|
||||
elif protectionlevel == '0x00000001':
|
||||
@@ -290,10 +104,10 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
protectionlevel = 'signatureOrSystem'
|
||||
|
||||
permission_dict[permission.getAttribute(
|
||||
'android:name')] = protectionlevel
|
||||
elif permission.getAttribute('android:name'):
|
||||
f'{ns}:name')] = protectionlevel
|
||||
elif permission.getAttribute(f'{ns}:name'):
|
||||
permission_dict[permission.getAttribute(
|
||||
'android:name')] = 'normal'
|
||||
f'{ns}:name')] = 'normal'
|
||||
# GENERAL
|
||||
if man_data_dic['min_sdk'] and int(man_data_dic['min_sdk']) < ANDROID_8_0_LEVEL:
|
||||
minsdk = man_data_dic.get('min_sdk')
|
||||
@@ -304,32 +118,32 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
for application in applications:
|
||||
# Esteve 23.07.2016 - begin - identify permission at the
|
||||
# application level
|
||||
if application.getAttribute('android:permission'):
|
||||
if application.getAttribute(f'{ns}:permission'):
|
||||
perm_appl_level_exists = True
|
||||
perm_appl_level = application.getAttribute(
|
||||
'android:permission')
|
||||
f'{ns}:permission')
|
||||
else:
|
||||
perm_appl_level_exists = False
|
||||
# End
|
||||
if application.getAttribute('android:usesCleartextTraffic') == 'true':
|
||||
if application.getAttribute(f'{ns}:usesCleartextTraffic') == 'true':
|
||||
ret_list.append(('clear_text_traffic', (), ()))
|
||||
if application.getAttribute('android:directBootAware') == 'true':
|
||||
if application.getAttribute(f'{ns}:directBootAware') == 'true':
|
||||
ret_list.append(('direct_boot_aware', (), ()))
|
||||
if application.getAttribute('android:networkSecurityConfig'):
|
||||
item = application.getAttribute('android:networkSecurityConfig')
|
||||
if application.getAttribute(f'{ns}:networkSecurityConfig'):
|
||||
item = application.getAttribute(f'{ns}:networkSecurityConfig')
|
||||
ret_list.append(('has_network_security', (item,), ()))
|
||||
do_netsec = item
|
||||
if application.getAttribute('android:debuggable') == 'true':
|
||||
if application.getAttribute(f'{ns}:debuggable') == 'true':
|
||||
ret_list.append(('app_is_debuggable', (), ()))
|
||||
debuggable = True
|
||||
if application.getAttribute('android:allowBackup') == 'true':
|
||||
if application.getAttribute(f'{ns}:allowBackup') == 'true':
|
||||
ret_list.append(('app_allowbackup', (), ()))
|
||||
elif application.getAttribute('android:allowBackup') == 'false':
|
||||
elif application.getAttribute(f'{ns}:allowBackup') == 'false':
|
||||
backupDisabled = True
|
||||
else:
|
||||
if not backupDisabled:
|
||||
ret_list.append(('allowbackup_not_set', (), ()))
|
||||
if application.getAttribute('android:testOnly') == 'true':
|
||||
if application.getAttribute(f'{ns}:testOnly') == 'true':
|
||||
ret_list.append(('app_in_test_mode', (), ()))
|
||||
for node in application.childNodes:
|
||||
an_or_a = ''
|
||||
@@ -337,18 +151,18 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
itemname = 'Activity'
|
||||
cnt_id = 'act'
|
||||
an_or_a = 'n'
|
||||
browse_dic = get_browsable_activities(node)
|
||||
browse_dic = get_browsable_activities(node, ns)
|
||||
if browse_dic['browsable']:
|
||||
browsable_activities[node.getAttribute(
|
||||
'android:name')] = browse_dic
|
||||
f'{ns}:name')] = browse_dic
|
||||
elif node.nodeName == 'activity-alias':
|
||||
itemname = 'Activity-Alias'
|
||||
cnt_id = 'act'
|
||||
an_or_a = 'n'
|
||||
browse_dic = get_browsable_activities(node)
|
||||
browse_dic = get_browsable_activities(node, ns)
|
||||
if browse_dic['browsable']:
|
||||
browsable_activities[node.getAttribute(
|
||||
'android:name')] = browse_dic
|
||||
f'{ns}:name')] = browse_dic
|
||||
elif node.nodeName == 'provider':
|
||||
itemname = 'Content Provider'
|
||||
cnt_id = 'cnt'
|
||||
@@ -365,9 +179,9 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
# Task Affinity
|
||||
if (
|
||||
itemname in ['Activity', 'Activity-Alias'] and
|
||||
node.getAttribute('android:taskAffinity')
|
||||
node.getAttribute(f'{ns}:taskAffinity')
|
||||
):
|
||||
item = node.getAttribute('android:name')
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
ret_list.append(('task_affinity_set', (item,), ()))
|
||||
|
||||
# LaunchMode
|
||||
@@ -381,9 +195,9 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
if (
|
||||
affected_sdk and
|
||||
itemname in ['Activity', 'Activity-Alias'] and
|
||||
(node.getAttribute('android:launchMode') == 'singleInstance'
|
||||
or node.getAttribute('android:launchMode') == 'singleTask')):
|
||||
item = node.getAttribute('android:name')
|
||||
(node.getAttribute(f'{ns}:launchMode') == 'singleInstance'
|
||||
or node.getAttribute(f'{ns}:launchMode') == 'singleTask')):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
ret_list.append(('non_standard_launchmode', (item,), ()))
|
||||
# Exported Check
|
||||
item = ''
|
||||
@@ -396,20 +210,20 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
protlevel = ''
|
||||
# End
|
||||
if itemname != 'NIL':
|
||||
if node.getAttribute('android:exported') == 'true':
|
||||
if node.getAttribute(f'{ns}:exported') == 'true':
|
||||
perm = ''
|
||||
item = node.getAttribute('android:name')
|
||||
if node.getAttribute('android:permission'):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
if node.getAttribute(f'{ns}:permission'):
|
||||
# permission exists
|
||||
perm = ('<strong>Permission: </strong>'
|
||||
+ node.getAttribute('android:permission'))
|
||||
+ node.getAttribute(f'{ns}:permission'))
|
||||
is_perm_exist = True
|
||||
if item != man_data_dic['mainactivity']:
|
||||
if is_perm_exist:
|
||||
prot = ''
|
||||
if node.getAttribute('android:permission') in permission_dict:
|
||||
if node.getAttribute(f'{ns}:permission') in permission_dict:
|
||||
prot = ('</br><strong>protectionLevel: </strong>'
|
||||
+ permission_dict[node.getAttribute('android:permission')])
|
||||
+ permission_dict[node.getAttribute(f'{ns}:permission')])
|
||||
# Esteve 23.07.2016 - begin - take into account protection level of the permission when claiming that a component is protected by it;
|
||||
# - the permission might not be defined in the application being analysed, if so, the protection level is not known;
|
||||
# - activities (or activity-alias) that are exported and have an unknown or normal or dangerous protection level are
|
||||
@@ -417,7 +231,7 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
# counted as exported.
|
||||
prot_level_exist = True
|
||||
protlevel = permission_dict[
|
||||
node.getAttribute('android:permission')]
|
||||
node.getAttribute(f'{ns}:permission')]
|
||||
if prot_level_exist:
|
||||
if protlevel == 'normal':
|
||||
ret_list.append(
|
||||
@@ -502,7 +316,7 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
cnt_id] + 1
|
||||
# Esteve 24.07.2016 - end
|
||||
|
||||
elif node.getAttribute('android:exported') != 'false':
|
||||
elif node.getAttribute(f'{ns}:exported') != 'false':
|
||||
# Check for Implicitly Exported
|
||||
# Logic to support intent-filter
|
||||
intentfilters = node.childNodes
|
||||
@@ -511,18 +325,18 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
if inf == 'intent-filter':
|
||||
is_inf = True
|
||||
if is_inf:
|
||||
item = node.getAttribute('android:name')
|
||||
if node.getAttribute('android:permission'):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
if node.getAttribute(f'{ns}:permission'):
|
||||
# permission exists
|
||||
perm = ('<strong>Permission: </strong>'
|
||||
+ node.getAttribute('android:permission'))
|
||||
+ node.getAttribute(f'{ns}:permission'))
|
||||
is_perm_exist = True
|
||||
if item != man_data_dic['mainactivity']:
|
||||
if is_perm_exist:
|
||||
prot = ''
|
||||
if node.getAttribute('android:permission') in permission_dict:
|
||||
if node.getAttribute(f'{ns}:permission') in permission_dict:
|
||||
prot = ('</br><strong>protectionLevel: </strong>'
|
||||
+ permission_dict[node.getAttribute('android:permission')])
|
||||
+ permission_dict[node.getAttribute(f'{ns}:permission')])
|
||||
# Esteve 24.07.2016 - begin - take into account protection level of the permission when claiming that a component is protected by it;
|
||||
# - the permission might not be defined in the application being analysed, if so, the protection level is not known;
|
||||
# - activities (or activity-alias) that are exported and have an unknown or normal or dangerous protection level are
|
||||
@@ -530,7 +344,7 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
# counted as exported.
|
||||
prot_level_exist = True
|
||||
protlevel = permission_dict[
|
||||
node.getAttribute('android:permission')]
|
||||
node.getAttribute(f'{ns}:permission')]
|
||||
if prot_level_exist:
|
||||
if protlevel == 'normal':
|
||||
ret_list.append(
|
||||
@@ -626,20 +440,20 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
if man_data_dic['min_sdk'] and man_data_dic['target_sdk'] and int(man_data_dic['min_sdk']) < ANDROID_4_2_LEVEL:
|
||||
if itemname == 'Content Provider' and int(man_data_dic['target_sdk']) < ANDROID_4_2_LEVEL:
|
||||
perm = ''
|
||||
item = node.getAttribute('android:name')
|
||||
if node.getAttribute('android:permission'):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
if node.getAttribute(f'{ns}:permission'):
|
||||
# permission exists
|
||||
perm = ('<strong>Permission: </strong>'
|
||||
+ node.getAttribute('android:permission'))
|
||||
+ node.getAttribute(f'{ns}:permission'))
|
||||
is_perm_exist = True
|
||||
if is_perm_exist:
|
||||
prot = ''
|
||||
if node.getAttribute('android:permission') in permission_dict:
|
||||
if node.getAttribute(f'{ns}:permission') in permission_dict:
|
||||
prot = ('</br><strong>protectionLevel: </strong>'
|
||||
+ permission_dict[node.getAttribute('android:permission')])
|
||||
+ permission_dict[node.getAttribute(f'{ns}:permission')])
|
||||
prot_level_exist = True
|
||||
protlevel = permission_dict[
|
||||
node.getAttribute('android:permission')]
|
||||
node.getAttribute(f'{ns}:permission')]
|
||||
if prot_level_exist:
|
||||
if protlevel == 'normal':
|
||||
ret_list.append(
|
||||
@@ -707,20 +521,20 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
if itemname == 'Content Provider' and int(man_data_dic['target_sdk']) >= 17:
|
||||
perm = ''
|
||||
item = node.getAttribute(
|
||||
'android:name')
|
||||
if node.getAttribute('android:permission'):
|
||||
f'{ns}:name')
|
||||
if node.getAttribute(f'{ns}:permission'):
|
||||
# permission exists
|
||||
perm = ('<strong>Permission: </strong>'
|
||||
+ node.getAttribute('android:permission'))
|
||||
+ node.getAttribute(f'{ns}:permission'))
|
||||
is_perm_exist = True
|
||||
if is_perm_exist:
|
||||
prot = ''
|
||||
if node.getAttribute('android:permission') in permission_dict:
|
||||
if node.getAttribute(f'{ns}:permission') in permission_dict:
|
||||
prot = ('</br><strong>protectionLevel: </strong>'
|
||||
+ permission_dict[node.getAttribute('android:permission')])
|
||||
+ permission_dict[node.getAttribute(f'{ns}:permission')])
|
||||
prot_level_exist = True
|
||||
protlevel = permission_dict[
|
||||
node.getAttribute('android:permission')]
|
||||
node.getAttribute(f'{ns}:permission')]
|
||||
if prot_level_exist:
|
||||
if protlevel == 'normal':
|
||||
ret_list.append(
|
||||
@@ -784,33 +598,33 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
|
||||
# GRANT-URI-PERMISSIONS
|
||||
for granturi in granturipermissions:
|
||||
if granturi.getAttribute('android:pathPrefix') == '/':
|
||||
if granturi.getAttribute(f'{ns}:pathPrefix') == '/':
|
||||
ret_list.append(
|
||||
('improper_provider_permission', ('pathPrefix=/',), ()))
|
||||
elif granturi.getAttribute('android:path') == '/':
|
||||
elif granturi.getAttribute(f'{ns}:path') == '/':
|
||||
ret_list.append(('improper_provider_permission', ('path=/',), ()))
|
||||
elif granturi.getAttribute('android:pathPattern') == '*':
|
||||
elif granturi.getAttribute(f'{ns}:pathPattern') == '*':
|
||||
ret_list.append(('improper_provider_permission', ('path=*',), ()))
|
||||
# DATA
|
||||
for data in data_tag:
|
||||
if data.getAttribute('android:scheme') == 'android_secret_code':
|
||||
xmlhost = data.getAttribute('android:host')
|
||||
if data.getAttribute(f'{ns}:scheme') == 'android_secret_code':
|
||||
xmlhost = data.getAttribute(f'{ns}:host')
|
||||
ret_list.append(('dialer_code_found', (xmlhost,), ()))
|
||||
|
||||
elif data.getAttribute('android:port'):
|
||||
dataport = data.getAttribute('android:port')
|
||||
elif data.getAttribute(f'{ns}:port'):
|
||||
dataport = data.getAttribute(f'{ns}:port')
|
||||
ret_list.append(('sms_receiver_port_found', (dataport,), ()))
|
||||
# INTENTS
|
||||
for intent in intents:
|
||||
if intent.getAttribute('android:priority').isdigit():
|
||||
value = intent.getAttribute('android:priority')
|
||||
if intent.getAttribute(f'{ns}:priority').isdigit():
|
||||
value = intent.getAttribute(f'{ns}:priority')
|
||||
if int(value) > 100:
|
||||
ret_list.append(
|
||||
('high_intent_priority_found', (value,), ()))
|
||||
# ACTIONS
|
||||
for action in actions:
|
||||
if action.getAttribute('android:priority').isdigit():
|
||||
value = action.getAttribute('android:priority')
|
||||
if action.getAttribute(f'{ns}:priority').isdigit():
|
||||
value = action.getAttribute(f'{ns}:priority')
|
||||
if int(value) > 100:
|
||||
ret_list.append(
|
||||
('high_action_priority_found', (value,), ()))
|
||||
@@ -864,60 +678,3 @@ def manifest_analysis(mfxml, man_data_dic, src_type, app_dir):
|
||||
return man_an_dic
|
||||
except Exception:
|
||||
logger.exception('Performing Manifest Analysis')
|
||||
|
||||
|
||||
def get_manifest_file(app_dir, app_path, tools_dir, typ):
|
||||
"""Read the manifest file."""
|
||||
try:
|
||||
manifest = ''
|
||||
if typ == 'aar':
|
||||
logger.info('Getting AndroidManifest.xml from AAR')
|
||||
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
|
||||
elif typ == 'apk':
|
||||
logger.info('Getting AndroidManifest.xml from APK')
|
||||
manifest = get_manifest_apk(app_path, app_dir, tools_dir)
|
||||
else:
|
||||
logger.info('Getting AndroidManifest.xml from Source Code')
|
||||
if typ == 'eclipse':
|
||||
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
|
||||
elif typ == 'studio':
|
||||
manifest = os.path.join(
|
||||
app_dir,
|
||||
f'app/src/main/{ANDROID_MANIFEST_FILE}')
|
||||
return manifest
|
||||
except Exception:
|
||||
logger.exception('Getting AndroidManifest.xml file')
|
||||
|
||||
|
||||
def get_manifest_apk(app_path, app_dir, tools_dir):
|
||||
"""Get readable AndroidManifest.xml.
|
||||
|
||||
Should be called before get_icon_apk() function
|
||||
"""
|
||||
try:
|
||||
manifest = None
|
||||
if (len(settings.APKTOOL_BINARY) > 0
|
||||
and is_file_exists(settings.APKTOOL_BINARY)):
|
||||
apktool_path = settings.APKTOOL_BINARY
|
||||
else:
|
||||
apktool_path = os.path.join(tools_dir, 'apktool_2.8.1.jar')
|
||||
output_dir = os.path.join(app_dir, 'apktool_out')
|
||||
args = [find_java_binary(),
|
||||
'-jar',
|
||||
apktool_path,
|
||||
'--match-original',
|
||||
'--frame-path',
|
||||
tempfile.gettempdir(),
|
||||
'-f', '-s', 'd',
|
||||
app_path,
|
||||
'-o',
|
||||
output_dir]
|
||||
manifest = os.path.join(output_dir, ANDROID_MANIFEST_FILE)
|
||||
if is_file_exists(manifest):
|
||||
# APKTool already created readable XML
|
||||
return manifest
|
||||
logger.info('Converting AXML to XML')
|
||||
subprocess.check_output(args) # lgtm [py/command-line-injection] md5 hash
|
||||
return manifest
|
||||
except Exception:
|
||||
logger.exception('Getting Manifest file')
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
# -*- coding: utf_8 -*-
|
||||
"""Android manifest analysis utils."""
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from xml.dom import minidom
|
||||
from xml.parsers.expat import ExpatError
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from mobsf.MobSF.utils import (
|
||||
find_java_binary,
|
||||
is_file_exists,
|
||||
)
|
||||
|
||||
# pylint: disable=E0401
|
||||
from .dvm_permissions import DVM_PERMISSIONS
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
ANDROID_4_2_LEVEL = 17
|
||||
ANDROID_5_0_LEVEL = 21
|
||||
ANDROID_8_0_LEVEL = 26
|
||||
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
|
||||
|
||||
|
||||
def get_manifest_file(app_dir, app_path, tools_dir, typ):
|
||||
"""Read the manifest file."""
|
||||
try:
|
||||
manifest = ''
|
||||
if typ == 'aar':
|
||||
logger.info('Getting AndroidManifest.xml from AAR')
|
||||
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
|
||||
elif typ == 'apk':
|
||||
logger.info('Getting AndroidManifest.xml from APK')
|
||||
manifest = get_manifest_apk(app_path, app_dir, tools_dir)
|
||||
else:
|
||||
logger.info('Getting AndroidManifest.xml from Source Code')
|
||||
if typ == 'eclipse':
|
||||
manifest = os.path.join(app_dir, ANDROID_MANIFEST_FILE)
|
||||
elif typ == 'studio':
|
||||
manifest = os.path.join(
|
||||
app_dir,
|
||||
f'app/src/main/{ANDROID_MANIFEST_FILE}')
|
||||
return manifest
|
||||
except Exception:
|
||||
logger.exception('Getting AndroidManifest.xml file')
|
||||
|
||||
|
||||
def get_manifest_apk(app_path, app_dir, tools_dir):
|
||||
"""Get readable AndroidManifest.xml.
|
||||
|
||||
Should be called before get_icon_apk() function
|
||||
"""
|
||||
try:
|
||||
manifest = None
|
||||
if (len(settings.APKTOOL_BINARY) > 0
|
||||
and is_file_exists(settings.APKTOOL_BINARY)):
|
||||
apktool_path = settings.APKTOOL_BINARY
|
||||
else:
|
||||
apktool_path = os.path.join(tools_dir, 'apktool_2.8.1.jar')
|
||||
output_dir = os.path.join(app_dir, 'apktool_out')
|
||||
args = [find_java_binary(),
|
||||
'-jar',
|
||||
apktool_path,
|
||||
'--match-original',
|
||||
'--frame-path',
|
||||
tempfile.gettempdir(),
|
||||
'-f', '-s', 'd',
|
||||
app_path,
|
||||
'-o',
|
||||
output_dir]
|
||||
manifest = os.path.join(output_dir, ANDROID_MANIFEST_FILE)
|
||||
if is_file_exists(manifest):
|
||||
# APKTool already created readable XML
|
||||
return manifest
|
||||
logger.info('Converting AXML to XML')
|
||||
subprocess.check_output(args) # User input is MD5 and validated
|
||||
return manifest
|
||||
except Exception:
|
||||
logger.exception('Getting Manifest file')
|
||||
|
||||
|
||||
def get_xml_namespace(xml_str):
|
||||
"""Get namespace."""
|
||||
m = re.search(r'manifest (.{1,250}?):', xml_str)
|
||||
if m:
|
||||
return m.group(1)
|
||||
logger.warning('XML namespace not found')
|
||||
return None
|
||||
|
||||
|
||||
def get_fallback():
|
||||
logger.warning('Using Fake XML to continue the Analysis')
|
||||
return minidom.parseString(
|
||||
(r'<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android='
|
||||
r'"http://schemas.android.com/apk/res/android" '
|
||||
r'android:versionCode="Failed" '
|
||||
r'android:versionName="Failed" package="Failed" '
|
||||
r'platformBuildVersionCode="Failed" '
|
||||
r'platformBuildVersionName="Failed XML Parsing" ></manifest>'))
|
||||
|
||||
|
||||
def bs4_xml_parser(xml_str):
|
||||
"""Attempt to parse XML with bs4."""
|
||||
logger.info('Parsing AndroidManifest.xml with bs4')
|
||||
try:
|
||||
soup = BeautifulSoup(xml_str, 'xml')
|
||||
return soup.prettify().encode('utf-8', 'ignore')
|
||||
except Exception:
|
||||
logger.exception('Parsing XML with bs4')
|
||||
return None
|
||||
|
||||
|
||||
def get_manifest(app_path, app_dir, tools_dir, typ):
|
||||
"""Get the manifest file."""
|
||||
try:
|
||||
ns = 'android'
|
||||
manifest_file = get_manifest_file(
|
||||
app_dir,
|
||||
app_path,
|
||||
tools_dir,
|
||||
typ)
|
||||
mfile = Path(manifest_file)
|
||||
if not mfile.exists():
|
||||
logger.warning('apktool failed to extract '
|
||||
'AndroidManifest.xml')
|
||||
return manifest_file, ns, get_fallback()
|
||||
logger.info('Parsing AndroidManifest.xml')
|
||||
xml_str = mfile.read_text('utf-8', 'ignore')
|
||||
ns = get_xml_namespace(xml_str)
|
||||
if ns and ns != 'android':
|
||||
logger.warning('Non standard XML namespace: %s', ns)
|
||||
try:
|
||||
return manifest_file, ns, minidom.parseString(xml_str)
|
||||
except ExpatError:
|
||||
logger.warning('Parsing AndroidManifest.xml failed')
|
||||
return manifest_file, ns, minidom.parseString(
|
||||
bs4_xml_parser(xml_str))
|
||||
except Exception:
|
||||
logger.exception('Parsing Error')
|
||||
return manifest_file, ns, get_fallback()
|
||||
|
||||
|
||||
def manifest_data(mfxml, ns):
|
||||
"""Extract manifest data."""
|
||||
try:
|
||||
logger.info('Extracting Manifest Data')
|
||||
svc = []
|
||||
act = []
|
||||
brd = []
|
||||
cnp = []
|
||||
lib = []
|
||||
perm = []
|
||||
cat = []
|
||||
icons = []
|
||||
dvm_perm = {}
|
||||
package = ''
|
||||
minsdk = ''
|
||||
maxsdk = ''
|
||||
targetsdk = ''
|
||||
mainact = ''
|
||||
androidversioncode = ''
|
||||
androidversionname = ''
|
||||
applications = mfxml.getElementsByTagName('application')
|
||||
permissions = mfxml.getElementsByTagName('uses-permission')
|
||||
permsdk23 = mfxml.getElementsByTagName('uses-permission-sdk-23')
|
||||
if permsdk23:
|
||||
permissions.extend(permsdk23)
|
||||
manifest = mfxml.getElementsByTagName('manifest')
|
||||
activities = mfxml.getElementsByTagName('activity')
|
||||
services = mfxml.getElementsByTagName('service')
|
||||
providers = mfxml.getElementsByTagName('provider')
|
||||
receivers = mfxml.getElementsByTagName('receiver')
|
||||
libs = mfxml.getElementsByTagName('uses-library')
|
||||
sdk = mfxml.getElementsByTagName('uses-sdk')
|
||||
categories = mfxml.getElementsByTagName('category')
|
||||
for node in sdk:
|
||||
minsdk = node.getAttribute(f'{ns}:minSdkVersion')
|
||||
maxsdk = node.getAttribute(f'{ns}:maxSdkVersion')
|
||||
# Esteve 08.08.2016 - begin - If android:targetSdkVersion
|
||||
# is not set, the default value is the one of the
|
||||
# minSdkVersiontargetsdk
|
||||
# = node.getAttribute (f'{ns}:targetSdkVersion')
|
||||
if node.getAttribute(f'{ns}:targetSdkVersion'):
|
||||
targetsdk = node.getAttribute(f'{ns}:targetSdkVersion')
|
||||
else:
|
||||
targetsdk = node.getAttribute(f'{ns}:minSdkVersion')
|
||||
# End
|
||||
for node in manifest:
|
||||
package = node.getAttribute('package')
|
||||
androidversioncode = node.getAttribute(f'{ns}:versionCode')
|
||||
androidversionname = node.getAttribute(f'{ns}:versionName')
|
||||
alt_main = ''
|
||||
for activity in activities:
|
||||
act_2 = activity.getAttribute(f'{ns}:name')
|
||||
act.append(act_2)
|
||||
if not mainact:
|
||||
# ^ Some manifest has more than one MAIN, take only
|
||||
# the first occurrence.
|
||||
for sitem in activity.getElementsByTagName('action'):
|
||||
val = sitem.getAttribute(f'{ns}:name')
|
||||
if val == 'android.intent.action.MAIN':
|
||||
mainact = activity.getAttribute(f'{ns}:name')
|
||||
# Manifest has no MAIN, look for launch activity.
|
||||
for sitem in activity.getElementsByTagName('category'):
|
||||
val = sitem.getAttribute(f'{ns}:name')
|
||||
if val == 'android.intent.category.LAUNCHER':
|
||||
alt_main = activity.getAttribute(f'{ns}:name')
|
||||
if not mainact and alt_main:
|
||||
mainact = alt_main
|
||||
|
||||
for service in services:
|
||||
service_name = service.getAttribute(f'{ns}:name')
|
||||
svc.append(service_name)
|
||||
|
||||
for provider in providers:
|
||||
provider_name = provider.getAttribute(f'{ns}:name')
|
||||
cnp.append(provider_name)
|
||||
|
||||
for receiver in receivers:
|
||||
rec = receiver.getAttribute(f'{ns}:name')
|
||||
brd.append(rec)
|
||||
|
||||
for _lib in libs:
|
||||
library = _lib.getAttribute(f'{ns}:name')
|
||||
lib.append(library)
|
||||
|
||||
for category in categories:
|
||||
cat.append(category.getAttribute(f'{ns}:name'))
|
||||
|
||||
for application in applications:
|
||||
try:
|
||||
icon_path = application.getAttribute(f'{ns}:icon')
|
||||
icons.append(icon_path)
|
||||
except Exception:
|
||||
continue # No icon attribute?
|
||||
|
||||
android_permission_tags = ('com.google.', 'android.', 'com.google.')
|
||||
for permission in permissions:
|
||||
perm.append(permission.getAttribute(f'{ns}:name'))
|
||||
for full_perm in perm:
|
||||
# For general android permissions
|
||||
prm = full_perm
|
||||
pos = full_perm.rfind('.')
|
||||
if pos != -1:
|
||||
prm = full_perm[pos + 1:]
|
||||
if not full_perm.startswith(android_permission_tags):
|
||||
prm = full_perm
|
||||
try:
|
||||
dvm_perm[full_perm] = DVM_PERMISSIONS[
|
||||
'MANIFEST_PERMISSION'][prm]
|
||||
except KeyError:
|
||||
# Handle Special Perms
|
||||
if DVM_PERMISSIONS['SPECIAL_PERMISSIONS'].get(full_perm):
|
||||
dvm_perm[full_perm] = DVM_PERMISSIONS[
|
||||
'SPECIAL_PERMISSIONS'][full_perm]
|
||||
else:
|
||||
dvm_perm[full_perm] = [
|
||||
'unknown',
|
||||
'Unknown permission',
|
||||
'Unknown permission from android reference',
|
||||
]
|
||||
|
||||
man_data_dic = {
|
||||
'services': svc,
|
||||
'activities': act,
|
||||
'receivers': brd,
|
||||
'providers': cnp,
|
||||
'libraries': lib,
|
||||
'categories': cat,
|
||||
'perm': dvm_perm,
|
||||
'packagename': package,
|
||||
'mainactivity': mainact,
|
||||
'min_sdk': minsdk,
|
||||
'max_sdk': maxsdk,
|
||||
'target_sdk': targetsdk,
|
||||
'androver': androidversioncode,
|
||||
'androvername': androidversionname,
|
||||
'icons': icons,
|
||||
}
|
||||
|
||||
return man_data_dic
|
||||
except Exception:
|
||||
logger.exception('Extracting Manifest Data')
|
||||
@@ -10,7 +10,7 @@ from django.conf import settings
|
||||
from django.shortcuts import render
|
||||
|
||||
from mobsf.MobSF.utils import print_n_send_error_response
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_analysis import (
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_utils import (
|
||||
get_manifest_file,
|
||||
)
|
||||
|
||||
|
||||
@@ -55,8 +55,10 @@ from mobsf.StaticAnalyzer.views.android.icon_analysis import (
|
||||
get_icon_apk,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_analysis import (
|
||||
get_manifest,
|
||||
manifest_analysis,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.manifest_utils import (
|
||||
get_manifest,
|
||||
manifest_data,
|
||||
)
|
||||
from mobsf.StaticAnalyzer.views.android.playstore import get_app_details
|
||||
@@ -166,7 +168,7 @@ def static_analyzer(request, api=False):
|
||||
app_dic['certz'] = get_hardcoded_cert_keystore(app_dic[
|
||||
'files'])
|
||||
# Manifest XML
|
||||
mani_file, mani_xml = get_manifest(
|
||||
mani_file, ns, mani_xml = get_manifest(
|
||||
app_dic['app_path'],
|
||||
app_dic['app_dir'],
|
||||
app_dic['tools_dir'],
|
||||
@@ -190,11 +192,12 @@ def static_analyzer(request, api=False):
|
||||
# Set Manifest link
|
||||
app_dic['mani'] = (
|
||||
f'../manifest_view/?md5={app_dic["md5"]}&type=apk')
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'])
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'], ns)
|
||||
app_dic['playstore'] = get_app_details(
|
||||
man_data_dic['packagename'])
|
||||
man_an_dic = manifest_analysis(
|
||||
app_dic['parsed_xml'],
|
||||
ns,
|
||||
man_data_dic,
|
||||
'',
|
||||
app_dic['app_dir'],
|
||||
@@ -337,7 +340,7 @@ def static_analyzer(request, api=False):
|
||||
'sha256'] = hash_gen(app_dic['app_path'])
|
||||
|
||||
# Manifest XML
|
||||
mani_file, mani_xml = get_manifest(
|
||||
mani_file, ns, mani_xml = get_manifest(
|
||||
'',
|
||||
app_dic['app_dir'],
|
||||
app_dic['tools_dir'],
|
||||
@@ -357,11 +360,12 @@ def static_analyzer(request, api=False):
|
||||
app_dic['mani'] = (
|
||||
f'../manifest_view/?md5={app_dic["md5"]}'
|
||||
f'&type={pro_type}')
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'])
|
||||
man_data_dic = manifest_data(app_dic['parsed_xml'], ns)
|
||||
app_dic['playstore'] = get_app_details(
|
||||
man_data_dic['packagename'])
|
||||
man_an_dic = manifest_analysis(
|
||||
app_dic['parsed_xml'],
|
||||
ns,
|
||||
man_data_dic,
|
||||
pro_type,
|
||||
app_dic['app_dir'],
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ IP2Location==8.10.0
|
||||
androguard==3.4.0a1
|
||||
apkid==2.1.5
|
||||
quark-engine==23.7.1
|
||||
frida==15.2.2
|
||||
frida==16.1.3
|
||||
tldextract==3.4.4
|
||||
openstep-parser==1.5.4
|
||||
svgutils==0.3.4
|
||||
|
||||
@@ -5,6 +5,8 @@ import re
|
||||
import requests
|
||||
|
||||
from bs4 import BeautifulSoup as Soup
|
||||
from bs4 import element
|
||||
|
||||
|
||||
ANDROID_PERMISSION_DOCS_URL = ('https://developer.android.com/'
|
||||
'reference/android/Manifest.permission')
|
||||
@@ -26,9 +28,20 @@ for pd in permission_divs:
|
||||
r'Protection level\: (\w+)', str(pd)).groups()[0]
|
||||
except AttributeError:
|
||||
protection_level = 'normal'
|
||||
description = str(pd.find('p').contents[0]).strip()
|
||||
desc = []
|
||||
for a in pd.find('p').contents:
|
||||
if type(a) is element.NavigableString:
|
||||
desc.append(str(a).strip().replace(
|
||||
'\n', '').replace('\t', '').replace('\xa0', ''))
|
||||
elif type(a) is element.Tag:
|
||||
if 'Protection level:' in a.text:
|
||||
break
|
||||
desc.append(str(a.text).strip().replace(
|
||||
'\n', '').replace('\t', '').replace('\xa0', ''))
|
||||
|
||||
description = ' '.join(desc)
|
||||
online_permissions[permission_name] = [protection_level,
|
||||
'TODO - fill in short description',
|
||||
'',
|
||||
description]
|
||||
|
||||
# check the permissions we currently have in dvm_permissions.py
|
||||
|
||||
Reference in New Issue
Block a user