Android App Penetration Testing & Frida Hooks

Frida for Penetration Testers: Seamless OkHttp3 SSL Pinning Bypass on Android

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction to SSL Pinning and the Penetration Tester’s Challenge

SSL pinning is a security mechanism employed by mobile applications to prevent man-in-the-middle (MiTM) attacks on network traffic. Instead of relying solely on the device’s trust store, applications ‘pin’ specific server certificates or public keys. This means the app will only trust connections to servers presenting one of these pre-defined certificates, effectively rejecting any others, including those issued by a proxy like Burp Suite. While this enhances security, it poses a significant challenge for penetration testers who need to intercept and analyze app traffic.

Traditional methods like installing custom CA certificates in the device’s trust store often fail against SSL pinning. This is where dynamic instrumentation tools like Frida come into play. Frida allows us to inject JavaScript into running processes, modify their behavior at runtime, and effectively bypass security controls like SSL pinning without needing to recompile the application.

Understanding OkHttp3 SSL Pinning Implementation

OkHttp3 is a popular HTTP client for Android and Java applications, renowned for its efficiency and robust features, including built-in SSL pinning capabilities. OkHttp3 implements SSL pinning primarily through its CertificatePinner class. Developers configure this pinner with a list of expected certificate hashes (SHA-1 or SHA-256) for specific hostnames. When a connection is established, the CertificatePinner intercepts the chain of certificates presented by the server and verifies if any of its public keys match the pinned hashes. If no match is found, the connection is aborted, typically resulting in an SSLHandshakeException.

A typical OkHttp3 client configured with pinning might look like this in Java/Kotlin:

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(new CertificatePinner.Builder()
        .add("example.com", "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=")
        .build())
    .build();

Our goal is to target and neutralize the functionality of this CertificatePinner at runtime.

Prerequisites for Frida-based Bypass

Before diving into the bypass, ensure you have the following setup:

  • Rooted Android Device or Emulator: Frida requires root privileges to inject into applications.
  • ADB (Android Debug Bridge): For connecting to your device and pushing files.
  • Frida Server: Running on your Android device.
  • Frida Client: Installed on your host machine (pip install frida-tools).
  • Target Android Application: An APK that uses OkHttp3 and implements SSL pinning.
  • Burp Suite (or similar proxy): To intercept and verify traffic.

Setting up Frida Server on Android

1. Download the correct Frida server for your device’s architecture from Frida Releases (e.g., frida-server-*-android-arm64).
2. Push it to your device and make it executable:

adb push frida-server /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/frida-server"

3. Start the Frida server on the device (you can run this in a separate adb shell or background it):

adb shell "/data/local/tmp/frida-server &"

4. Verify it’s running by listing processes:

frida-ps -U

Identifying the Target Method for Hooking

For OkHttp3’s CertificatePinner, the critical method to hook is check. This method is responsible for performing the actual certificate validation against the pinned hashes. By hooking this method and making it return immediately, we can effectively bypass the pinning logic.

You can verify the exact method signature using tools like `jadx-gui` or by decompiling the APK with `apktool` and inspecting the Smali code or Java source. Typically, the relevant check method in okhttp3.CertificatePinner takes a java.lang.String (hostname) and a java.util.List (of peer certificates) as arguments.

Crafting the Frida JavaScript Hook

Our Frida script will use `Java.perform` to ensure the hook executes within the Java VM context. We then use `Java.use` to get a handle to the `okhttp3.CertificatePinner` class. The crucial part is identifying the correct `check` method overload. The most common signature for the pinning check is `check(String hostname, List peerCertificates)`.

Java.perform(function() {
    console.log("[+] Starting OkHttp3 SSL pinning bypass script...");

    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');

        // Hooking the 'check' method that takes a hostname and a list of certificates
        CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, peerCertificates) {
            console.log("[+] OkHttp3 CertificatePinner.check() bypassed for host: " + hostname);
            // Simply return without calling the original implementation,
            // effectively disabling the pinning check for this invocation.
            return;
        };
        console.log("[+] OkHttp3 CertificatePinner.check(String, List) hook applied successfully.");

    } catch (e) {
        console.error("[-] Error hooking OkHttp3 CertificatePinner: " + e.message);
    }

    // Additionally, some apps might use other overloads or alternative pinning methods.
    // A common variant to consider is 'check(String hostname, Certificate... certificates)'
    // if the list is passed as varargs, though less common with the public API.
    // Or even direct calls to 'findMatchingCertificates'.

    // For completeness, if the app uses a custom TrustManager, you might need to hook
    // 'checkClientTrusted' and 'checkServerTrusted' methods in 'javax.net.ssl.X509TrustManager'.
    // However, for standard OkHttp3 pinning, the above hook is usually sufficient.
});

Explanation of the Script

  • Java.perform(function() { ... });: Ensures that our JavaScript code runs within the context of the Android application’s Java VM.
  • var CertificatePinner = Java.use('okhttp3.CertificatePinner');: Obtains a reference to the `okhttp3.CertificatePinner` class, allowing us to interact with its methods.
  • CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(...) { ... };: This is the core of the bypass. We specifically target the `check` method that accepts a `String` (for the hostname) and a `List` (for the peer certificates). By setting its `implementation`, we replace the original method’s logic with our own. Our custom implementation simply prints a message and then returns immediately, effectively skipping the entire certificate validation logic that would otherwise throw an exception.

Executing the Frida Script

Save the above JavaScript code to a file, for example, `okhttp3_bypass.js`. Then, execute it against your target application using Frida:

frida -U -f com.example.targetapp -l okhttp3_bypass.js --no-pause
  • -U: Specifies that Frida should attach to a USB-connected device.
  • -f com.example.targetapp: Spawns and attaches to the application with the package name `com.example.targetapp`. Replace this with your actual target app’s package name.
  • -l okhttp3_bypass.js: Loads our JavaScript bypass script.
  • --no-pause: Prevents Frida from pausing the application at startup, allowing it to run normally while our script is injected.

Once the command is executed, Frida will inject your script, and any subsequent network connections made by the OkHttp3 client within the application should now bypass the SSL pinning checks. You will see console messages indicating the bypass is active for each host encountered.

Verification and Interception

With the Frida script running, configure your Android device to proxy its network traffic through Burp Suite. Open Burp Suite, ensure the proxy listener is active, and the Burp CA certificate is installed on your device (in the user trust store, if not already). Now, interact with the target application. You should be able to intercept and inspect all network requests and responses from the application in Burp Suite, confirming the successful SSL pinning bypass.

Conclusion

Frida is an indispensable tool for advanced mobile application penetration testing. By understanding how common libraries like OkHttp3 implement security features like SSL pinning, penetration testers can craft precise and effective runtime hooks. The ability to dynamically modify application behavior provides an unparalleled advantage in security assessments, allowing for thorough analysis of network communications even when strong defensive measures are in place. This targeted OkHttp3 bypass demonstrates the power and flexibility of Frida for overcoming modern mobile security challenges.

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner