Pages

Monday, December 14, 2015

Attacking Bound Services on Android

Many times when exploring a new Android device, I encounter exported Services that expose a Binder interface, known as "bound Services".  Unlike an unbound Service, we can't just use the `am` command to interact with the Service; rather, we'll need to actually create an Android application.  Creating a client to connect to a bound Service can be tricky even with the Service's source code, and without it can be even more confusing. There are plenty of blogs and tutorials that talk about creating bound Services, but I couldn't find any focus on interacting with bound Services from an attacker's perspective (no source).

In this post I'll create an application that exposes a bound Service, show you how to find and interpret bound Services in an application's disassembled Smali code, and present a tool to automate AIDL reconstruction.  This post will not be an in depth description of bound Services.

Creating the Bound Service in Java

First, we'll create an application, "com.jakev.boundserver" that defines our exported bound Service. This bound Service will support a single method, called "exec()", that accepts a command as a String, and executes it, and returns the output (please do not actually add this to your applications). The source code for this project (and APK) can be downloaded from the links at the end of this post.

We'll create the bound Service in 3 steps:
  • Declaring the new component in the "AndroidManifest.xml"
  • Creating the Android Interface Definition Language ("AIDL") interface
  • Creating a new Service class and implementing the "onBind()" method

In our AndroidManifest.xml we declare a new exported Service, ".ITestService":



Next, we create our AIDL interface, called "com.jakev.boundserver.aidl.TestInterface".  As described above, our "exec()" method will accept a single String argument, and return a String value:


Last, we create our Service class "com.jakev.boudserver.ITestService.java".  We need to implement the "onBind()" method, and return an instance to our "TestInterface" interface created above:


In order to interact with this Service, we'll need to create an application and include the AIDL file above.  As a developer, we'd probably distribute a JAR library that contains the AIDL file "TestInterface.aidl" and other supporting classes so that others can develop applications to interface with our new Service. As an attacker, we will likely not have this luxury.

Exploring the Service APK

Let's assume we find the "com.jakev.boundserver" application installed on a device, and stumble on this exported ".ITestService" Service.  We don't have the source code for the application; we just have the APK.  Let's pull the application and unpack it with `apktool`:


As a first step, let's look our ".ITestService" Service class, found at "smali/com/jakev/boundserver/ITestService.smali".  The "onBind()" method is pretty straightforward, and we can see that the Service is instantiating an inner class, "ITestService$1", and returning it.  This is due to the way we called the "new TestInterface.Stub() { }" above.


Opening "smali/com/jakev/boundserver/ITestService$1.smali" shows that the class is implementing a class "com.jakev.boundserver.aidl.TestInterface$Stub", which we have not looked at yet.  In the virtual methods section we see the actual implementation of the "exec()" method.  As a reverse engineer, you'd likely start with this method for determining the capabilities of the "exec()" method.


Next, let's look at what happened to our AIDL file.  There are now 3 different classes, called "TestInterface.smali", "TestInterface$Stub.smali", and "TestInterface$Stub$Proxy.smali", shown below.


Android Studio was nice enough to generate these for us when we built our application. There are plenty of papers that talk about the exact role of each of these, so I wont spend a lot of time talking about that.  The key takeaways here are:

  • The "TestInterface" class will always implement the "android.os.IInterface" class. It contains an abstract definition of each of the Binder methods.
  • The "TestInterface$Stub" class will always implement the "android.os.Binder" class, and contains the Binder transaction identifiers stored as fields.  The naming convention looks like "TRANSACTION_{methodName}".  These are the same ID fields used when calling services with the `service` command-line utility.
  • The "TestInterface$Stub$Proxy" class doesn't implement or extend any class, but contains the return type and parameter information for each Binder method.
You can use the following searches for if you're looking at a new application and want to enumerate Binder interfaces and their method implementation:

Finding any AIDL classes:
grep -r "super.*IInterface" ./smali

Finding implementation of AIDL:
grep -r "super.*${AIDL class from above}" ./smali

With these pieces of information, we can reconstruct the AIDL, and include this in our client application. You can do this manually, or you can use a tool I've created called 'GenerateAIDL.jar' that uses the DexLib2 library to parse an application's DEX code and outputs AIDL files that you can quickly add to your Service client.


If we open this file, we should see a AIDL interface similar to the one we created above:


Keep in mind this is just a trivial example.  There likely will be more than one method (and possibly some imported libraries) in a real-world example.

Attacking Bound Services

Now we're going to use the AIDL we just generated above to create a client application, "com.jakev.serverclient" that interacts with the ".ITestService".  I've tried to make this project as generic as possible, so it can be reused with ease.

The first step is to actually create/import our AIDL.  We want to add the AIDL we generated above to the proper folder, being mindful of the package name:


Next, we'll modify the "MainActivty" class I've created as a template.  First, add the AIDL above as an import, and add an object of this class called "service":


Next, change the class name of the Intent created in the "initService()" method, to the service you're interacting with:


Finally, we modify the "onServiceConnect()" method of our local "ServiceConnection" class to actually interact with the bound Service.  In this example, we're calling the "exec()" method, and supplying the "id" command, then recording this value in the Android logs.


If we build, install, and run our client application, we should see the output of the `id` command in the logs:


Conclusions

Given the correct permissions, an attacker can interact with bound Services just like other components.  It is important to inventory your application and confirm that the components that are exported are the ones you actually want exported.  For any component that performs sensitive actions (such as executing commands!!), make sure you apply the correct permissions.

Resources

  • http://stackoverflow.com/questions/15330233/remote-service-with-aidl-file-serviceconnection-never-called
  • http://developer.android.com/reference/android/content/ServiceConnection.html
  • http://developer.android.com/guide/components/bound-services.html
  • http://developer.android.com/guide/components/aidl.html
  • https://newcircle.com/s/post/48/implementing_remote_interface_using_aidl

Downloads

Friday, May 29, 2015

Hooking SQLCipher with Xposed

Recently, a coworker of mine approached me regarding an Android application that was using the SQLCipher library.  For those unfamiliar with SQLCipher, it provides "transparent, secure 256-bit AES encryption" of Android SQLite3 databases, which is something that many security professionals recommend (myself included).  In order to see the actual data inside the database, it is often necessary to obtain the password used to perform the encryption, which can be tricky if it is not just in plain-text in the APK.

@MDSecLabs wrote a blog post a little over a year ago that describes how the SQLCipher library works, and how it is possible to obtain database encryption keys using the CydiaSubstrate, a hooking framework.  They also provide a Cydia "tweak" that can be used to steal the SQLCipher encryption key used by an application (for testing purposes), which is exactly what my coworker was interested in!

Unfortunately, the CydiaSubstrate doesn't always work on all devices (in my experience), and doesn't overall seem as maintained as the Xposed framework, which accomplishes roughly the same goal.  After downgrading his test device from Lollipop (to Jelly Bean) and installing the MDSec Cydia tweak, he was still unable to get the secret key to print in the log buffers, even though the test application provided by MDSec worked fine.  What gives?

It turns out that the SQLCipher library has changed a bit since MDSec created their tweak, and there are now new overloaded variants of the "openOrCreateDatabase" method, which is what MDSec is attempting to hook (you can see the current methods here).  Depending on how the application you're testing uses the SQLCipher API, you may see the key printed in the logs.

I did some quick Googling and did not see an Xposed version of the MDSec tweak, so I decided to write my own variation.  To use it, you'll need a rooted device and the Xposed framework installed.  You can download the APK from my GitHub.

Now, you can install the APK, reboot your device, and use your SQLCipher enabled app as you normally would. In a different window, check the logcat buffers for the secret key used by the application.  Here are the contents of the log buffers when running the MDSec MyEncryptedApp test application.


Thanks to MDSec for doing the research in determine the appropriate method to hook and for creating the Cydia tweak.  If anyone has any questions or feature requests, feel free to reach out to me!

Links