#NewPermissionModel
Explore tagged Tumblr posts
joym-blog · 9 years ago
Text
AndroidSecurity Model
Android is a privilege separated operating system where every application runs with a unique system ID, called the UID, in its own sandbox. A central design point of the Android security architecture is that no application has permission to adversely impact other applications, the operating system or the user. Every application in Android has four high level components namely, Activity, Service, Broadcast Receiver and Content Provider. Each component can interact with each other with the help of something called Intent. Every component inside an application can call each other by just passing intents and does not need any permission to do so. A component can access other components outside its own application sandbox if the Android system grants it permission.
 Android’s Old Permission Mechanism
Permissions can be either defined by the Android system or can be defined by app developer. Each of the system defined permissions is used to protect some resource on the phone. Typical examples of system defined permissions are CALL_PHONE used to make phone calls, INTERNET used to open network sockets, SEND_SMS used to send messages, CAMERA used to capture images etc. Custom permissions defined by the app developer are typically used to protect components created by the developer. Each permission in android has a name, label, description, permission group and protection level. The name must be unique and is used in code to refer to the permission. Permissions with conflicting names cannot exist in the Android system. Label and description are used to describe the role of the permission to the user. Permission group is used to specify the category of the permission like camera, Calendar, contacts, location etc. This allows the user to grant a set of permissions in a single action. Finally and most importantly protection level specifies the procedure the Android system should take to grant permission to the requesting application. Android permissions have four protection levels namely -- normal which is granted by the system automatically at install time, dangerous which is granted by the system at install time only if the user approves, signature which is granted only if the application requesting it is signed with the same key as the one used to sign the application that declared the permission, and finally signatureOrSystem which is the same as signature but is only granted to apps in the Android system image. The default level is normal. An application must request upfront all the permissions it needs. When an application is installed, the package manager goes through all the permissions requested by the app. Normal permissions are granted by default by the system, signature permissions are granted by the system if and only if the app requesting the permission has the same signature as the app that defined the permission, dangerous permissions are granted only if the user approves it. If a user denies even a single dangerous permission then the app is not installed. An app is also not installed if it defines a permission that is already defined in the system.
Enforcing Permission
Once an app has been installed in the system, it has been granted all the permissions it had requested at install time. When a particular component is called, the android system checks if the uids of the caller and the callee match. If they match access is instantly granted. If they do not match then it checks if the callee component is exported or public. If it is not exported then the call fails. However, if exported then it checks whether it is protected by a permission. If it is protected by a permission then it checks if the caller component has been granted that permission by referring to the permission name attribute. If permission has been granted then the caller is allowed to call the callee else a security exception is thrown. However, if the exported callee component is not protected by a permission then the caller is granted access anyway.  
 Android’s New Permission Mechanism
Recently Android launched the M permission model, which introduced a new app permission model. Android made two primary changes to their security model.
Dangling Permissions Previously Android did not revoke any permission once a permission was granted to an app. This led to various problems of privilege escalation where even the most stringent signature permissions could be by passed by non-privileged apps to gain unauthorized access. In the new permissions model a permission whose definition does not exist in the system anymore will be revoked. Consider a case where app A creates a custom permission with name customPermA. Let us say that customPermA is used to protect a content provider in app B. Let us assume that app C needs to access the content provider in app B. It requests for customPermA and is granted by the system. If a user for some reason uninstalls app A then app C’s permission to access the content provider in app B will be revoked. This could lead to some unexpected behavior if app C tries to access the content provider in B after the revocation. It could even lead to app C crashing due to a security exception. However, it does solve the problem where a malicious app could use dangling permissions to gain unauthorized access to a component.
Run time permission check Older versions of Android granted all permission at install time. The downside of this approach was that user’s weren’t allowed to install the app if they disagreed with even one permission. For instance, if a user wanted to install a gaming app and that app wanted access to the internet but the user was not comfortable with it,then the user would have to deny installation. With android’s new permission mechanism users do not have to make that choice at install time. Permissions with protection level dangerous in Android’s new model are not granted when the app is installed. Permissions with protection level normal and protection level signature are still granted at install time though. When the app runs and one of its component wants to access another component protected by a permission whose protection level is dangerous then the user is prompted for approval. If the user approves then access is granted. If the user denies then access is not granted and the app developer should handle the access denial gracefully. If the user denies permission but tries to access the functionality that requires this permission again then the user is prompted again for approval but this time with a “do not ask again” option. If the user approves then access is granted. But if the user denies and selects “do not ask again” then user will never be prompted again and the app will never be granted this permission. Also, users have the option of revoking permissions. For instance, if a user wants to upload an image to the Facebook app then Facebook will request the user to grant access to gallery. The user grants access but can revoke it after uploading the app. Therefore, developers are advised to always check whether their app has the required permission before accessing a resource and handle it gracefully if permission is not granted otherwise their apps might crash. Stalling the granting of permission right up to the time when it is actually required could make the user sit up and take notice as opposed to granting permissions at install time where the user was most likely to grant it without paying much attention.
 Does it solve the problem of unauthorized access?
Android’s run time permission might force the user to pay more attention before granting permission requests; it still leaves the responsibility with the user. If the user grants permission that does not mean that the caller is authorized to call the callee. Moreover, permissions with protection level normal and signature still behave the same way as they used to in the older model. Just like the old model, the new permission model is not enough to prevent unauthorized access. It needs to be complemented with a system where the identity of the caller is also verified before access is granted to it.
Android’s fix to revoke permissions whose definitions do not exist in the system does solve the problem of overriding a permission of higher protection level with a permission of lower protection level. However, it introduces a new problem of availability. Revoking permissions from existing apps could lead to unpredictable behavior if the developer has not handled such a situation. This could lead to the app not working at all especially if the permission revoked was critical to its functioning. A better approach would be to check if the permission and not only the permission name requested by the caller is the same as the permission protecting the callee.
The following approach could be a better alternative to solve the dangling permissions problem and the unauthorized access problem. Assumptions: Let A and B be two components in the android system. Let P(A) be the permission protecting A and let Pu(B) be the permission that B requests. Please note that P(A) and Pu(B) are not mere permission names but the permission object itself. It holds all the information about that permission like name, label, protection level etc. Also, let WL(A) be a white list of components and their signatures that are allowed to access component A. Also, let grant(Pu(B)) be a function that returns true if Pu(B) has been granted by the system else returns false. Finally, let L(P(A)) be the protection level of that permission.  Algorithm: if UID(A) = UID(B) grant access else       if grant(Pu(B))     if P(A) = Pu(B)         if L(P(A)) = "signature             grant access         else if B in WL(A) or WL(A) is empty             grant access         else             reject call else reject call else reject call
This approach solves the problem of dangling permissions  without affecting the availability of the app and it also provides a white list mechanism through which components will be able to explicitly specify who is authorized to access it. The Android source could be modified to perform this check every time a component is called by another.
0 notes