TL;DR
If an application hardcodes a certificate (or its fingerprint), it’s possible to bypass SSL pinning. This guide explains how, covering techniques like replacing the certificate with your own, using proxies, and modifying the app if possible. Success depends on the implementation details of the pinning.
Understanding SSL Pinning
SSL pinning is a security measure where an application only trusts specific certificates (or their public keys) instead of relying on Certificate Authorities (CAs). Hardcoding these certificates directly into the app makes it harder for attackers to intercept traffic, but isn’t foolproof.
Steps to Bypass SSL Pinning
- Identify the Hardcoded Certificate:
- Static Analysis: Use tools like dex2jar and jd-gui (for Android apps) or similar disassemblers for other platforms to examine the application’s code. Look for strings that resemble certificate fingerprints (SHA-256 is common) or base64 encoded certificates.
- Dynamic Analysis: Use a proxy like Burp Suite or mitmproxy to intercept network traffic. Even if the app pins, you might see the expected certificate fingerprint in the handshake process.
- Proxy Setup: Configure a proxy server (Burp Suite is recommended).
- Generate Your Own Certificate: Create a self-signed certificate with the same common name (CN) as the target server. OpenSSL is useful for this:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=example.com' - Import Certificate into Proxy: Add your generated certificate as a trusted CA in the proxy server.
- Intercept and Replace: When the app connects, the proxy intercepts the SSL handshake. Configure the proxy to replace the target server’s certificate with your own.
Burp Suite allows you to do this easily through its ‘SSL Settings’ and ‘Certificate Replacement’ features.
- Locate Pinning Code: Find where the application checks the certificate fingerprint. This often involves comparing a hash of the presented certificate against a hardcoded value.
- Patch the Code: There are several approaches:
- Remove Pinning: The simplest (but most invasive) is to remove the pinning code entirely.
- Bypass Check: Modify the check to always return true, effectively disabling pinning.
// Original Code (example) if (!certificateMatchesPin(presentedCertificate)) { throw new SSLHandshakeException("Certificate Pinning Failed!"); } // Patched Code if (true) { // Allow connection regardless of certificate } - Add Your Certificate: Add your own certificate fingerprint to the list of trusted fingerprints.
- Rebuild and Install: Recompile the application with your changes (if possible) and install it on your device.
- Hook Pinning Functions: Use a framework like Frida to hook the functions responsible for certificate validation.
- Modify Return Values: Change the return value of these functions to bypass the pinning check.
// Example Frida script snippet (very simplified) Interceptor.attach(Module.findExportByName("libssl.so", "SSL_CTX_verify"), { onEnter: function(args) { // Modify args[0] to accept any certificate args[0].modifyWriteValue(ptr('0x0'), ptr('1')); // Example - may need adjustment } });
- If the app uses ATS, it might have additional security configurations. Bypassing pinning in this case could require disabling ATS entirely or modifying its settings.
Important Considerations
- Complexity: Bypassing SSL pinning can be complex and requires a good understanding of networking, cryptography, and the target application’s code.
- App Updates: App updates may re-introduce pinning or change the hardcoded certificates, requiring you to repeat these steps.
- Legal Implications: Bypassing security measures without authorization is illegal in many jurisdictions. This information is for educational purposes only.