Certificate pinning (also known as TLS pinning) is a security technique used in mobile applications to protect against man-in-the-middle attacks. It works by hard coding the server’s SSL certificate or public key into the application, so only connections to a trusted server are accepted.
Instead of trusting all TLS certificates issued by a Certificate Authority, the mobile application stores the certificate or public key of a specific server in advance.
This article will be looking at disabling certificate pinning for Android applications. Doing this allows you to use traffic inspection tools such as BurpSuite, to identify vulnerabilities in the web requests being transmitted.
Intercepting Traffic with BurpSuite
First, let’s configured BurpSuite to intercept traffic from an emulated Android device without certificate pinning in place.
Download and install BurpSuite community edition. Open BurpSuite and set the proxy so it’s listening on all IP addresses (not just localhost).

In Android Studio go to File > Settings, and set the IP address of our computer running BurpSuite.

Start an Android emulator, and navigate to the address of the BurpSuite host on port 8080. Download the certificate.

In the emulator, go into Android settings and install the downloaded certificate.

Browse to a website of your choosing using the Chrome web browser.

You should see this traffic is being routed through BurpSuite for inspection.

We can intercept Chrome’s traffic, since it’s referring to the operating systems certificate store. Applications that implement certificate pinning use their own certificate store, so this method won’t work.
InjuredAndroid has a challenge that implements certificate pinning. Open the application and navigate to flag 17.

When we enter information into the text box and click submit, nothing will happen – and we won’t see any traffic in BurpSuite. We’re going to need to bypass certificate pinning to get around this.

Bypassing TLS Pinning
Frida is a dynamic instrumentation toolkit that allows you to intercept and modify function calls in real-time. Objection is a runtime mobile exploration toolkit that builds on Frida. We’re going to be using Objection to bypass certificate pinning.
There are two ways of disabling certificate pinning, either using a rooted device or by recompiling the target application.
Using a Rooted Device
First, install objection and frida-tools in a pip virtual environment.
1 2 3 4 | python3 -m venv OBJECTION source OBJECTION/bin/activate cd OBJECTION/ ./bin/pip3 install objection frida-tools |
Install some required packages for objection.
1 | sudo apt install apksigner zipalign |
Check the installed Frida version.
1 2 | ./bin/frida --version 16.6.6 |
Setup an Android Nexus 6 virtual machine, release name S, API version 31 – x86_64.

Next, we need to install frida-server on the Anroid device. Note, the version of frida-server downloaded needs to match the version of frida we installed with pip.
1 2 3 4 5 6 7 8 9 | user@ubuntu:~$ adb root restarting adbd as root user@ubuntu:~$ wget https://github.com/frida/frida/releases/download/16.6.6/frida-server-16.6.6-android-x86_64.xz user@ubuntu:~$ unxz frida-server-16.6.6-android-x86_64.xz user@ubuntu:~$ mv frida-server-16.6.6-android-x86_64 frida-server user@ubuntu:~$ adb push frida-server /data/local/tmp/ frida-server: 1 file pushed, 0 skipped. 367.7 MB/s (114016280 bytes in 0.296s) user@ubuntu:~$ adb shell "chmod 755 /data/local/tmp/frida-server" user@ubuntu:~$ adb shell "/data/local/tmp/frida-server &" |
With frida-server uploaded to the rooted device, we can now use objection to interact with the installed APK and patch out certificate pinning.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | user@ubuntu:~/Android/OBJECTION$ ./bin/frida-ps -U | grep -i injured 6388 InjuredAndroid user@ubuntu:~/Android/OBJECTION$ ./bin/objection -g InjuredAndroid explore Using USB device `Android Emulator 5556` Agent injected and responds ok! _ _ _ _ ___| |_|_|___ ___| |_|_|___ ___ | . | . | | -_| _| _| | . | | |___|___| |___|___|_| |_|___|_|_| |___|(object)inject(ion) v1.11.0 Runtime Mobile Exploration by: @leonjza from @sensepost [tab] for command suggestions b3nac.injuredandroid on (google: 12) [usb] # android sslpinning disable (agent) Custom TrustManager ready, overriding SSLContext.init() (agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.verifyChain() (agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.checkTrustedRecursive() (agent) Registering job 393082. Type: android-sslpinning-disable b3nac.injuredandroid on (google: 12) [usb] # |
You should now be able to intercept the challenge flag.

Application Patching
We can use Objection to patch the APK file to disable certificate pinning, without needing a rooted device.
Before starting Objection, make sure you have an Android device emulator running.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ./bin/objection patchapk -s InjuredAndroid.apk No architecture specified. Determining it using `adb`... Detected target device architecture as: x86_64 Using latest Github gadget version: 16.6.6 Patcher will be using Gadget version: 16.6.6 Detected apktool version as: 2.11.0 Running apktool empty-framework-dir... I: Removing framework file: 1.apk Unpacking InjuredAndroid.apk App already has android.permission.INTERNET Target class not specified, searching for launchable activity instead... Reading smali from: /tmp/tmplya0inl5.apktemp/smali/b3nac/injuredandroid/MainActivity.smali Injecting loadLibrary call at line: 10 Attempting to fix the constructors .locals count Current locals value is 0, updating to 1: Writing patched smali back to: /tmp/tmplya0inl5.apktemp/smali/b3nac/injuredandroid/MainActivity.smali Copying Frida gadget to libs path... Rebuilding the APK with the frida-gadget loaded... Built new APK with injected loadLibrary and frida-gadget Performing zipalign Zipalign completed Signing new APK. Signed the new APK Copying final apk from /tmp/tmplya0inl5.apktemp.aligned.objection.apk to InjuredAndroid.objection.apk in current directory... Cleaning up temp files... |
If you get any errors, you probably want to remove the apt version of apktool, and install the latest version by following these instructions.
Now, remove the un-patched APK file from the emulated device.
1 2 3 4 5 | adb shell emu64xa16k:/ $ pm list packages | grep -i injured package:b3nac.injuredandroid emu64xa16k:/ $ pm uninstall b3nac.injuredandroid Success |
Then install the new APK package.
1 2 3 | adb install InjuredAndroid.objection.apk Performing Streamed Install Success |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ./bin/objection explore Using USB device `Android Emulator 5554` Agent injected and responds ok! _ _ _ _ ___| |_|_|___ ___| |_|_|___ ___ | . | . | | -_| _| _| | . | | |___|___| |___|___|_| |_|___|_|_| |___|(object)inject(ion) v1.11.0 Runtime Mobile Exploration by: @leonjza from @sensepost [tab] for command suggestions b3nac.injuredandroid on (google: 12) [usb] # b3nac.injuredandroid on (google: 12) [usb] # android sslpinning disable (agent) Custom TrustManager ready, overriding SSLContext.init() (agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.verifyChain() (agent) Found com.android.org.conscrypt.TrustManagerImpl, overriding TrustManagerImpl.checkTrustedRecursive() (agent) Registering job 119346. Type: android-sslpinning-disable b3nac.injuredandroid on (google: 12) [usb] # |
In Conclusion
Bypassing certificate pinning using a rooted device often proves the most reliable method. To get either method to work will probably require running an older Android API version, as Frida needs to add API support, and it’s a moving target.