SSL Pinning Bypass for Android Using Frida

SSL pinning is one of the most common defenses mobile app developers use to stop attackers and researchers from intercepting network traffic. For penetration testers, security researchers, and QA engineers, bypassing this protection is often the first real obstacle in any Android app assessment. Frida has become the go-to instrumentation framework for solving this problem, letting you hook into an app's TLS validation logic at runtime without touching the original APK's source code.

This guide walks through the full process: understanding how SSL pinning works, setting up your testing environment, and using Frida scripts to defeat pinning implementations across common Android libraries like OkHttp, TrustManager, and Network Security Config.

What Is SSL Pinning and Why It Blocks Traffic Interception

SSL pinning (also called certificate pinning) hardcodes a specific certificate, public key, or hash inside the app itself. When the app makes an HTTPS request, it checks the server's certificate against this pinned value instead of relying solely on the device's trusted certificate store.

This means that even if you install a proxy tool like Burp Suite or mitmproxy and add its CA certificate to your device, the app will still refuse the connection because the certificate presented by your proxy does not match the pinned value.

Common places pinning logic lives in an Android app include:

  • Custom X509TrustManager implementations
  • OkHttp's CertificatePinner class
  • Network Security Configuration XML files
  • Native libraries (compiled C/C++ code using OpenSSL or BoringSSL)

Understanding where the pinning check happens is the first step before writing or choosing a Frida script to bypass it.

Setting Up Your Environment for Frida-Based Testing

Before you touch any bypass scripts, your environment needs to be ready. SageFox Cybersecurity's mobile testing labs typically use a rooted Android device or emulator, since Frida's full capabilities require root access to inject into arbitrary processes.

Requirements

  • A rooted Android device or an emulator such as Genymotion or a rooted AVD
  • Frida server binary matching your device's CPU architecture
  • Frida tools installed on your host machine
  • Burp Suite or mitmproxy configured as an intercepting proxy
  • ADB configured and device visible via adb devices

Installing Frida Tools on Your Host

bash

pip install frida-tools frida
frida --version

Pushing Frida Server to the Device

Download the frida-server binary that matches your device architecture from the official Frida GitHub releases page, then push it to the device.

bash

adb push frida-server-16.3.3-android-arm64 /data/local/tmp/frida-server
adb shell "chmod 755 /data/local/tmp/frida-server"
adb shell "su -c /data/local/tmp/frida-server &"

Confirm the server is running and reachable from your host.

bash

frida-ps -U

If this command lists running processes on the device, your instrumentation bridge is live. If you're struggling to get consistent results across different device models, SageFox Cybersecurity's team handles this setup as part of every mobile penetration test engagement, so the technical groundwork never becomes a blocker for your assessment timeline.

Identifying the Pinning Implementation Before Writing a Hook

Blindly running a generic bypass script sometimes works, but a more reliable approach starts with identifying exactly which pinning mechanism the target app uses.

Decompiling the APK

bash

apktool d target-app.apk -o target_output

Search the decompiled smali or Java-like output for common pinning indicators.

bash

grep -r "CertificatePinner" target_output/
grep -r "X509TrustManager" target_output/
grep -r "checkServerTrusted" target_output/

You can also use jadx for a cleaner Java-style view of the decompiled code.

bash

jadx -d jadx_output target-app.apk

This step matters because OkHttp-based pinning, custom TrustManager pinning, and native-layer pinning each require a different Frida hooking strategy. Skipping this reconnaissance step is the most common reason bypass attempts fail on the first try.

Universal SSL Pinning Bypass Script Using Frida

The most widely used starting point in the community is a universal bypass script that hooks multiple known pinning classes simultaneously. Below is a working example targeting several common implementations.

javascript

Java.perform(function () {
   console.log("[*] Starting universal SSL pinning bypass");

   // Bypass OkHttp3 CertificatePinner
   var CertificatePinner = Java.use("okhttp3.CertificatePinner");
   CertificatePinner.check.overload("java.lang.String", "java.util.List").implementation = function (hostname, certs) {
       console.log("[+] OkHttp3 CertificatePinner.check bypassed for " + hostname);
       return;
   };

   // Bypass custom TrustManager checkServerTrusted
   var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl");
   TrustManagerImpl.verifyChain.implementation = function (untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
       console.log("[+] TrustManagerImpl.verifyChain bypassed for " + host);
       return untrustedChain;
   };

   // Bypass HostnameVerifier
   var HostnameVerifier = Java.use("javax.net.ssl.HostnameVerifier");
   HostnameVerifier.verify.implementation = function (hostname, session) {
       console.log("[+] HostnameVerifier bypassed for " + hostname);
       return true;
   };
});

Save this as universal_bypass.js and run it against the target application.

bash

frida -U -f com.target.package -l universal_bypass.js --no-pause

The --no-pause flag lets the application launch and run naturally while the hooks are applied at startup, which is important since many pinning checks fire during the app's initial network handshake.

Bypassing OkHttp CertificatePinner Specifically

Some apps rely heavily on OkHttp's CertificatePinner, especially newer apps built with Retrofit. If the universal script above does not fully work due to overload mismatches, a more targeted hook is often needed.

javascript

Java.perform(function () {
   var CertificatePinner = Java.use("okhttp3.CertificatePinner");
   var overloads = CertificatePinner.check.overloads;

   overloads.forEach(function (overload) {
       overload.implementation = function () {
           console.log("[+] Overload bypassed: " + overload.argumentTypes.map(t => t.className).join(", "));
       };
   });
});

This approach dynamically loops through every overloaded version of the check method, which is useful when app developers use less common method signatures that a static script might miss.

Bypassing Native Layer Pinning in Compiled Libraries

Some high-security apps, particularly in banking and fintech, implement pinning inside native C/C++ code compiled into .so libraries. This is significantly harder to bypass because there is no Java method to hook directly.

Locating the Native Function

bash

frida-trace -U -i "SSL_CTX_set_verify" com.target.package

This traces calls to OpenSSL or BoringSSL functions responsible for certificate verification.

Hooking with Frida's Native Interceptor

javascript

var sslLib = Process.findModuleByName("libssl.so");
var sslVerifyAddr = sslLib.findExportByName("SSL_get_verify_result");

Interceptor.attach(sslVerifyAddr, {
   onLeave: function (retval) {
       console.log("[+] SSL_get_verify_result forced to X509_V_OK");
       retval.replace(0);
   }
});

Native bypasses like this require a solid understanding of the OpenSSL verification flow, and results vary between BoringSSL and OpenSSL builds. For teams without in-house reverse engineering depth, this is exactly the kind of engagement SageFox Cybersecurity supports directly, working through obfuscated native binaries so your internal team can focus on remediation rather than reverse engineering.

Verifying the Bypass Worked

Once your hooks are in place, the real test is whether your intercepting proxy now sees decrypted traffic.

Steps to Confirm

  1. Configure Burp Suite or mitmproxy as the device's proxy in Wi-Fi settings.
  2. Install the proxy's CA certificate on the device (system store for rooted devices, or user store with the bypass active).
  3. Launch the app with the Frida script attached.
  4. Watch the proxy's HTTP history tab for populated requests.

If requests appear in your proxy with full request and response bodies visible, the pinning bypass succeeded. If the app crashes or shows a network error screen, this usually indicates either an incomplete hook (missing an overload or a secondary check) or a native-layer check you have not yet addressed.

Common Errors and How to Fix Them

Frida Cannot Attach to the Process

This usually happens due to SELinux restrictions or Magisk-based root hiding. Try running Frida server with an alternate name to avoid detection.

bash

adb shell "mv /data/local/tmp/frida-server /data/local/tmp/sagefox-agent"
adb shell "su -c /data/local/tmp/sagefox-agent &"

App Detects Root or Frida and Force Closes

Some apps run root detection and Frida detection checks before the pinning logic even executes. In these cases, you need an additional bypass script targeting root detection libraries such as RootBeer, alongside your SSL pinning hooks.

Certificate Still Rejected After Hooking

Double check that you have covered all overloads of the relevant method. Many pinning bypass failures come from developers using a slightly different method signature than the one targeted in a copy-pasted public script.

Best Practices for Professional Mobile App Assessments

  • Always test bypass scripts against a non-production build first when working with client applications
  • Document every hook applied, including class names and method signatures, for your final report
  • Combine static analysis (apktool, jadx) with dynamic analysis (Frida) rather than relying on one alone
  • Re-test after each app update, since pinning implementations frequently change between releases
  • Maintain a private library of hooks tailored to frameworks you encounter repeatedly, such as OkHttp, Retrofit, and Volley

Consistent methodology matters more than any single script. SageFox Cybersecurity's mobile security team builds custom hook chains for each client engagement rather than relying on generic public scripts, since production apps frequently combine multiple pinning layers to slow down researchers.

Key Takeaways

SSL pinning bypass using Frida is a foundational skill for anyone performing Android application security assessments. The technique requires understanding where pinning logic lives in an app, whether that is Java-level OkHttp checks, custom TrustManager implementations, or native compiled libraries, and then applying the correct hooking strategy for that layer.

A universal script gets you started quickly, but real-world engagements often demand targeted hooks, native interception, and root detection bypasses working together. If your organization needs a thorough assessment of how your mobile application handles certificate validation and network security controls, SageFox Cybersecurity's mobile penetration testing team can identify these weaknesses before attackers do, delivering a clear remediation path your development team can act on immediately.