The Lab #59: Bypassing certificate pinning with Frida and Fiddler - part 2
Rooting a virtual mobile Android Device to install Frida and discover API endpoints under the hood of apps
In the latest episode of The Lab we’ve seen how to intercept the network traffic generated by an app by using a network inspection tool like Fiddler Everywhere.
As mentioned at the end of the article, this setup is not always working, especially for apps that take their security more seriously.
In fact, apps like X won’t work since they use what is called “certificate pinning”.
What is certificate pinning?
Certificate pinning is a security technique used in apps (especially mobile apps) to ensure that the app is communicating with the correct server. It helps prevent man-in-the-middle (MITM) attacks by binding (or "pinning") the app to a specific certificate or a set of certificates.
Here's how it works:
Certificate Trust: Normally, when an app connects to a server over HTTPS, the server presents an SSL/TLS certificate. The app checks if this certificate is issued by a trusted Certificate Authority (CA) that is recognized by the device's operating system. If it is, the connection proceeds; if not, the connection is terminated.
Man-in-the-Middle Attack Risk: In some scenarios, an attacker could potentially intercept this connection by presenting a fake certificate from another CA that is trusted by the device. This is where certificate pinning adds an extra layer of security. This is the case when we try to use Fiddler Everywhere.
Pinning Process: In certificate pinning, the app is hardcoded to accept only a specific certificate or a set of certificates. When the app connects to the server, it checks the server's certificate against the pinned certificate(s) it has stored. If the certificate does not match, the connection is refused, even if the certificate is issued by a trusted CA. Since the Fiddler certificate does not match the ones pinned in the app, this stops working.
Cons of this approach: While certificate pinning increases security, it also introduces some challenges. For instance, if the server's certificate changes (e.g., due to renewal or switching to a new CA), the app needs to be updated with the new pinned certificate, or it will fail to connect.
Given this explanation, we have two roads to understand how an app works and which endpoints it calls:
get the source code of the app
hijack the app controls on the certificate, and this is what we’ll do
Using Frida to bypass certificate checks
Frida is an instrumentation toolkit that allows developers, security researchers, and reverse engineers to inject custom scripts into running applications. It can be used to bypass certificate pinning in an app by hooking into the app's network functions and modifying its behavior.
Frida can be used to intervene and bypass an app's certificate pinning checks by dynamically altering the app's behavior at runtime. Here’s how this process generally works:
1. Identifying Certificate Pinning Functions
Targeting Key Functions: Apps that implement certificate pinning typically have specific functions or methods responsible for verifying the server’s certificate against the pinned certificate or public key. These functions could be part of the app's code or within libraries the app uses, such as network libraries (e.g., OkHttp for Android) or SSL/TLS libraries.
Common Targets: Functions like
SSL_verify_cert_chain
,X509TrustManager
,X509TrustManagerImpl
, or custom certificate validation methods are often targeted for bypassing.
2. Hooking with Frida
Injecting Code: Frida allows you to inject JavaScript code into the running app. This injected code can hook into specific functions within the app. Hooking means you can intercept the function call, inspect its parameters, and modify its return values or even bypass the function entirely.
Example: If an app uses X509TrustManager to validate certificates, Frida can hook into this class’s checkServerTrusted method. This method typically checks whether the server's certificate matches the pinned certificate.
3. Modifying the Validation Logic
Bypassing Logic: Once hooked, you can alter the behavior of the function. For example, instead of allowing the function to perform its usual checks, you can make it return a value that indicates the certificate is valid, regardless of what the actual certificate is.
Force Acceptance: A typical modification would be to force the method to always return
true
(or another success indicator) or skip the validation code entirely, effectively making the app accept any certificate provided by the server. In our case, we’ll force the acceptance of the Fiddler certificate.
Using Frida to perform such tasks will require a rooted mobile phone (a device that allows the user to have root access to it): since I don’t have any spare device for this, I’ve decided to follow the procedure to create a virtual device on Android Studio and root it.
So let’s recap the steps we need to take:
Install Android Studio and create a virtual device
Install adb on your Desktop to control the virtual device from the command line
Instal RootADV to root the device
Finally, install Frida
Run Frida by attaching it to the app we want to see the network traffic
As always, if you want to have a look at the code, you can access the GitHub repository, available for paying readers. For this article, I’ve created different files under the folder 59.FRIDA that are split by the task they perform.
If you’re one of them but don’t have access to it, please write me at pier@thewebscraping.club to get it.
Before starting the tutorial, let me make a disclaimer: I’ve followed this procedure on a Mac and I’ll share with you the versions of the software I’ll use in the guide. Since this procedure is complex and the tools are always updated, this might not work with other releases. Please keep an eye on the dependencies of the various tools.
Install Android Studio and create a virtual device
This is a standard procedure, you can just install Android Studio from the official page.
Once the download and the installation procedure has finished, we can create our virtual device.
Following some suggestions from the web, I’ve created a Pixel8 Phone with Play Store with Android version S.
Once the device is created, we need to set up Fiddler in it by installing the certificate and trusting it. For this, you can just follow the official guidelines on this page.
Install ADB on your desktop
ADB stands for Android Debug Bridge. It is a versatile command-line tool that allows developers, testers, and security researchers to communicate with and control Android devices from a computer. ADB is an essential part of the Android SDK (Software Development Kit) and is widely used for various tasks in Android development and debugging.
Common ADB Commands
Device Management: ADB can be used to list connected devices (adb devices), reboot the device (adb reboot), or install and uninstall apps (adb install, adb uninstall).
Shell Access: You can open a command-line shell on the device (
adb shell
) to interact directly with the Android operating system, execute commands, and explore the file system.Logcat: ADB can be used to view system logs (adb logcat), which is essential for debugging apps and understanding what is happening under the hood.
File Transfer: ADB supports transferring files to and from the device (adb push and adb pull).
App Debugging: Developers can use ADB to start or stop apps, view app processes, and interact with the app in real-time.
This step depends on your platform, but if you follow the instructions from this page you should be able to download and install it by the Android SDK tool.
Install RootADV
As explained in the official repository of RootADV, it is a script to
root your Android Studio Virtual Device (AVD), with Magisk (Stable, Canary or Alpha)
patch its fstab
download and install the USB HOST Permissions Module for Magisk
install custom build Kernel and its Modules
download and install AOSP prebuilt Kernel and its Modules
My main source for this procedure has been this video, which is well made even if I had to skip some steps to adapt the process to my setup.
After cloning the Git Repository locally
git clone https://gitlab.com/newbit/rootAVD.git
we need to find out the correct AVD for our setup. To do so, we need to list all the available AVDs
./rootAVD.sh ListAllAVDs
and, in our configuration, select
./rootAVD.sh system-images/android-31/google_apis_playstore/arm64-v8a/ramdisk.img
In fact, if we have a look at our virtual device configuration, we have installed Android 31 with also Google Play store and it’s emulating an arm64 architecture.
If we do everything correctly, the magic happens, the phone reboots and we’ll find out a new app, called Magisk, installed on the virtual device.
To test the configuration, we can run this script on our desktop with ADB, testing the ability to get root privileges on the device.
First, we list all the running virtual devices with
adb devices
Then we select the rooted one and connect to its shell
adb -s emulator-5554 shell
After the connection, we’re on the device command line. If we’re able to execute the su command on it, it means we have rooted correctly the device.
But we’re only halfway!
Installing Frida server and its command line tools
Keep reading with a 7-day free trial
Subscribe to The Web Scraping Club to keep reading this post and get 7 days of free access to the full post archives.