Another day with mobile application security assessments…
I generally carry out android application assessments so, I will focus mostly on the android platform. Moreover, I like android because it is open, allows a lot of customisations and it is based on the linux kernel.The protection mechanisms in mobile platforms really annoy during any security assessment. Generally, assessments are carried on a rooted android device/emulator as they provide better control and flexibility. But the security mechanisms written in an android application prove hindrance during such an assessment.
When it comes to security assessments, it would not be good to not mention the ubiquitous “BURPSUITE”. It is an interception tool to observe and manipulate the https traffic between a client and a server. But, SSL pinning checks don’t allow “BURPSUITE” to do an MITM and intercept the requests and responses. More information on SSL pinning can be found here and here. So, what do we do now??
There are many workarounds for the above problems. One is the static approach where the “apk” is decoded with tools like “apktool” and the particular logic is changed in the “smali” files and then the “apk” is re-packaged again. But, this method is likely to fail if there is any “tamper-detection” code in place. The other method uses a dynamic approach where the particular logic is changed while the application is running which means code would be injected at runtime in the process. As we can see, the second method doesn’t require re-packaging. Also, at times, some adb tricks help e.g. the adb activity manager can be used to directly start the next activity to bypass any logic present in the preceding activity.
Here, in this post, I will be following the dynamic approach. I will be using the “Frida Framework” to bypass the above mentioned checks (root detection and SSL pinning) on a real android device. First, let us understand what exactly “Frida” is.
Frida
In short, it is a dynamic instrumentation framework, which enables function hooking and allows to provide a definition to it during runtime. Basically, it injects JavaScript code into a process. Suppose, there is a function called “foo” in a program with a specific body/implementation. Using “Frida”, one can change the body/implementation of the “foo” function during runtime. “Frida” supports a variety of platforms like Windows, macOS, GNU/Linux, iOS, Android, and QNX. More information on “Frida” can be found here.
There are three modes of operation in “Frida”, viz. Injected
, Embedded
& Preloaded
. Here, I will be using the injected mode of operation. More information on these modes can be found here.
One disadvantage of the injected mode is that it requires a rooted device. On the other hand, the embedded mode of operation doesn’t require a rooted device but requires re-packaging of the “apk” i.e. the “Frida gadget” (a shared library) needs to be embedded in the “apk”. So, it depends upon the situation as to which mode of operation one needs to follow during an assessment.
Sample Implementation in android with JavaScript
Java.perform(function(){var sample_class = Java.use("fully qualified class name");//Creating object of the above class
var obj = sample_class.$new()sample_class.function_name.implementation = function(){//new logic for the function here};});
In the above example, the function within the sample class is overwritten with a new implementation using JavaScript API for Frida. For more information please refer this and this.
Before starting off, let’s set up the lab.
Lab Setup
The following are required to setup the android lab for dynamic instrumentation with “Frida”.
- Rooted android device/emulator
- Correct Frida server pushed in the android device
- Python3, Frida tools and Android platform tools installed on the computer
- JADX — to decompile jar files into readable java source
- BURPSUITE community — to intercept the requests & responses
One may follow this guide to configure BURPSUITE with the android device and for setting up “Frida” one may follow this.
Steps
- Connect the android device to the computer and make sure that
Developer Options
andUSB
Debugging
are turned on as shown in figure 1. - Then check if the device is detected with adb tool as shown in figure 2.
- Find the ABI with adb tool by issuing the command
adb shell getprop ro.product.cpu.abi
as shown in figure 3. - Download the correct Frida server (for android) from here and push it to the android device with adb as shown in figure 5.
- Change the permissions of the Frida server to make it executable and run it in the background by issuing the commands as shown in figure 5.
- Install Frida tools on the computer by typing the following in a terminal
pip install frida-tools
and check if Frida tools are able to communicate with the running Frida server as shown in figure 6. Here, we try to list down the running processes on the android device. - Push the BURPSUITE certificate (in crt format) to the android device as shown in figure 7 and install it on the device.
Analysing the root detection logic
Load the android package (apk)in JADX tool and search for the terms “root”, “rooted” etc. In my application, I found that the “isDeviceRooted” function is responsible for the root detection logic. If a boolean “false” is returned from this function then it would mean that the device is not rooted.
When the application is run on a rooted device, a message is displayed and the application terminates.
Root detection bypass
I quickly wrote an implementation for the function responsible for root detection in JavaScript.
Please note that the above implementation for root detection bypass may vary from application to application.
I typed the following in a terminal to run the android application and inject the JavaScript code to overwrite the implementation of the “isDeviceRooted” function. Hence, the root detection logic was bypassed using Frida.
frida -l root-detection-bypass.js -U -f com.redacted.app --no-pause
Analysing SSL pinning logic
Searching for terms like “pinning”, “SSLContext”, “KeyStore”, “TrustManagers” etc. in JADX, revealed the function which is responsible for SSL pinning. There was an “init” function inside the “MyVolley” class of the application. For more information on SSL pinning in android please refer this and this. On trying to intercept the traffic with BURPSUITE, the following certificate error was encountered due to certificate pinning checks.
SSL pinning bypass
After analysing the function for some time, I wrote the following JavaScript code to redefine the implementation of the function responsible for the logic. Also, combining it with the previous root detection bypass script and thus, producing the final script as follows.
Please note that the above script was created by referring the Java source code of the application and thus may vary from application to application.
Running the above script as shown below to disable root detection checks and SSL pinning checks in the android application.
frida -l root-ssl-pin-bypass.js -U -f com.redacted.app --no-pause
Thanks for reading!