Welcome to Android Security Part 2.  Previously, I discussed some of the basics you as an app author can do to better secure your apps.  This simple steps can go a long way to secure your app and its data on the device.  In this installment, I will discuss Android defined permissions and how you can use them to secure your apps.

 

Android Permissions vs. Linux Permissions

In Android Security Part 1, I outlined the Android App Sandbox, which is the base of security within the platforms.  The sandbox enforces permissions at the user/group level for an app process.  As you recall, this is managed by the Linux kernel which is powering our Android device.  Linux kernel defined user and group IDs are used along with filesystem permissions to keep an app contained to its memory and storage areas.  But what happens when you have app components which are exposed using Android facilities such as Intents or Binder?  This is where Android’s permissions architecture comes into play.

The Android framework builds upon the base security model by defining additional permissions which are required to use certain features.  For example, in order to use the GPS on the device, your app must hold the Manifest.permission.ACCESS_FINE_LOCATION permission.  If we look at this definition in the Android documentation, you can see that it is defined to be a String: “android.permission.ACCESS_FINE_LOCATION”.  This permission, like many others, are defined by the framework and enforced appropriately.  They provide finer grained control over protected resources or features in the system.  These permissions are “granted” by the user when they install an app.  The biggest complaints about the permissions system are that it is a blanket “all or nothing” at install time and there are so many of them it is confusing to users.  Google is supposedly working on a solution to this, but that is a topic for another day.

Therefore, Android permissions enhance the existing sandbox architecture by adding an additional layer of refinement by feature or function.  But, what is the system really doing here?

 

Permissions Enforcement

The Android security framework, by way of the PackageManager, maintains a list of the permissions which are defined on the device and granted to specific packages.  These permissions are strings which for a given section of the framework or an application have special meaning.  By convention, they are namespaced in their structure.  Looking closely at our previous example of ACCESS_FINE_LOCATION, we can see see it is namespaced to be part of the Android platform: android.permission.ACCESS_FINE_LOCATION. The Android framework and/or applications use these permissions in one of two ways: framework enforcement or application/service enforcement.

With framework enforced Android permissions, the framework ensures the calling packaged has been grated the permission before it takes any action.  For example, before calling startActivity() with an action of ACTION_CALL to trigger a call without going through the dialer UI, your app must hold the permission CALL_PHONE. The framework enforces this and the startActivity call will fail with a SecurityException if the calling app package does not hold the correct permission.

With application/service enforced Android permissions, the app receiving the specific request performs the enforcement. Many of the core Android services use this approach for finer grain controls on specific features. Take the Vibrator as an example. Using this object, you can cause the vibrator on the device to activate and provide the user with haptic feedback. Any app that wishes to use the vibrator must hold the VIBRATE permission. But, unlike the previous example where an Activity is started via an Intent, the Vibrator class gives the app what appears to be direct control. This is not exactly true. The Vibrator class is a thin app side proxy to a service provided by the framework. Like most of the other system provided services, it runs in a privileged process which has UI (and therefore filesystem access) to the exposed kernel device driver interface. Behind the scenes there is a Binder/IBinder involved, but that’s a much bigger discussion. When the app calls through the Vibrator class to the service, the service checks that the caller holds the appropriate permission before taking any action.

It’s important to point out that within each of our device’s running apps’ process there is an instance of the Dalvik VM and the necessary framework components for the app to function.  Even NDK (i.e. native) apps are constrained in this way, they do not get to break out of this Android security paradigm if they use platform services. And, because of the security sandbox by process/UID/GID/filesystem the process is constrained to not get direct access to underlying hardware.  So no short circuiting just by dropping to C/C++ code!

 

Securing Your App With Permissions

So the Android permissions system sounds pretty good: sandboxing as a base and framework enforced or app enforced.  But how does this help you secure your app?  That is the point of this blog, right?  Here’s where the real power comes into play with Android permissions: you can define your own.  Your package can define its own set of permissions and use them as it sees fit.  After all, they are just special strings which hold some meaning for an application or feature.  How do we define them?  In our AndroidManifest.xml:

<manifest>
...
<permission
    android:name="com.hiqes.sample.frm_enf_perm"
    android:description="@string/frm_enf_perm_descr"
    android:label="@string/frm_enf_perm_label"
    android:permissionGroup="com.hiqes.sample.easy_perms"
    android:protectionLevel="signature" />
<permission
    android:name="com.hiqes.sample.app_enf_perm"
    android:description="@string/app_enf_perm_descr"
    android:label="@string/app_enf_perm_label"
    android:permissionGroup="com.hiqes.sample.easy_perms"
    android:protectionLevel="signature" />
</manifest>

In the above example, I’ve created two permissions called com.hiqes.sample.frm_enf_perm and com.hiqes.sample.app_enf_perm. These permissions belong to a custom permission group, com.hiqes.sample.easy_perms. Groups are just what they sound like: logical groupings of permissions. Just like the permissions themselves, you can define your own. They are not required, but can be helpful for users to see. The protectionLevel attribute at the end is an important one. This is how the system knows how to treat the permission when an app requires it (more on that shortly.) There are four levels: normal, dangerous, signature and signatureOrSystem. See the Android documentation for details about each. To secure our apps, any one of them could be used. But, in our case we want only our app or apps to have access to our components so we’ll use signature.

Framework Enforcement of Android Permissions

Now that we have defined our permissions, how do we get the Android Framework to enforce one?  The framework needs to know what components from our app require the permission in order to be started.  Let’s use an Activity as an example.  In our app, InternalActivity is one which is only intended to be used internally by the app but it can handle multiple Intents.  We can force the system to not export our Activity, but let’s also secure it with a permission. This is accomplished by adding the attribute android:permission to our activity tag:

<manifest>
...
    <activity
        android:name=".InternalActivity"
        android:permission="com.hiqes.sample.frm_enf_perm"
        android:exported="false" >

        <intent-filter>
            <action android:name="com.hiqes.sample.INTERNAL_ACTION1" />
            <category android:name="android.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action android:name="com.hiqes.sample.INTERNAL_ACTION2" />
            <category android:name="android.category.DEFAULT" />
        </intent-filter>
        ...
    </activity>
....
</manifest>

With this in place, only apps which holds the “framework enforced” custom permission can actually start our internal Activity. We can also start it ourselves because we define the permission. The permission attribute also exists for Service, BroadcastReceiver and ContentProvider, allowing us to let the framework handle our enforcement.

App Enforced Android Permissions

The remaining mechanism we have to enforce Android Permissions is at runtime. As I mentioned before, this is commonly used in Service component. The calling process ID (PID) and user ID (UID) can be acquired from the Binder object. Using this information, we can call Context.checkCallingPermission. If we know the calling package name (such as via Activity.getCallingPackage, we can use a similar method from Context or even PackageManager to verify the permission. If the calling package does not hold the permission, these calls will return an error. But how do you propagate that back to the caller? You can manually throw a SecurityException, or you can use some convenience methods as part of the Context object: enforceCallingOrSelfPermission, enforceCallingPermission and enforcePermission. These methods will perform the permissions check and throw a SecurityException for you if the caller does not hold the correct permission.  The “self” variants of the methods allow you to write code which will allow your application to use your components without your app also declaring that it uses the permission. Let’s say I have a custom service which exposes an API called pushData(MyData newData) which I’m protecting with my custom permission. In my service method implementation the first thing I would do is check the calling permission:

public class MyInternalServiceImpl extends IMyInternalService.Stub {
    private Context mCtx;
    ...
    public int pushData(MyData newData) {
        String perm = mCtx.getString(R.string.app_enf_perm_name);
        String errMsg = mCtx.getString(R.string.push_data_perm_fail);
        mCtx.enforceCallingOrSelfPermission(perm, errMsg);

        //  Now do the real work and push new data
        ...
    }
}

Now my custom service is protecting itself so that only apps which hold my custom permission can access this API. So now instead of only having “blanket” permissions for an entire component, I can selectively enforce a custom Android permission at the exposed API level.

Using the Custom Android Permissions

Since our app defines the permissions, it can also use the components which require them.  But, what if we have other applications which we wish to allow use of our components?  Remember, we used the signature protection level with our permissions.  So other apps which have been signed by our same key will be able to use the permissions once installed.  The system will actually fail the installation if a package indicates it uses the custom permission and it is not signed by the same key of the package which defined the permission.  Just like Android defined permissions, our second app would indicate in its manifest that it uses our custom permission:

<manifest>
...
    <uses-permission android:name="com.hiqes.sample.frm_enf_perm" />
    <uses-permission android:name="com.hiqes.sample.app_enf_perm" />
</manifest>

Armed with this information about custom Android permissions, you can now take some extra steps to secure the components of your application. In my next Android Security installment, I’ll talk about hiding APIs in a library or at the platform level. Until then, happy coding and keep things safe!