Root/Jailbreak Detection & SSL Pinning in KMM: Implementation & Bypass Strategies

0
1
Root/Jailbreak Detection & SSL Pinning in KMM: Implementation & Bypass Strategies


Within the first weblog of the KMM sequence, we launched Kotlin Multiplatform Cellular (KMM) and its cross-platform benefits.

On this half, we go deeper into cell safety in KMM apps, specializing in:

  • Root/Jailbreak detection
  • SSL pinning
  • How attackers bypass these protections
  • Sensible tricks to defend towards bypasses

However, earlier than that, let’s rapidly recap what KMM is.

Kotlin Multiplatform Cellular (KMM) allows builders to write down shared code for each Android and iOS, whereas nonetheless sustaining platform-specific implementations the place essential.

For the sake of simplicity, we have divided this weblog into two sections:

  1. Implementation: Key methods to safe your KMM app.
  2. Bypass: How attackers circumvent these protections and defend towards them.

🔑 Key takeaway Safety will not be a one-time implementation. It’s an ongoing cycle of hardening → monitoring → defending towards new bypass methods.

KMM utility safety

Safety is a vital concern in KMM purposes, particularly for safeguarding delicate knowledge and stopping unauthorised entry.

Whereas the 2 important safety mechanisms utilized in cell purposes, i.e., Root/Jailbreak detection and SSL pinning, assist enhance safety, attackers usually try to bypass them utilizing varied strategies.

Danger

Impression if exploited

Instance

Root/Jailbreak

Attackers acquire elevated privileges

Extract delicate knowledge, alter API calls

Weak SSL pinning

Man-in-the-middle (MITM) assaults

Consumer credentials intercepted

Lacking safety layers

Non-compliance with safety requirements

Banking apps failing PCI DSS audits

Part 1: Implementation

1. Root/Jailbreak detection

Root detection helps stop attackers from working the appliance on a compromised machine. A rooted or jailbroken machine gives elevated privileges that permit attackers to switch app behaviour,  extract delicate data, or manipulate API requests.

Since KMM helps each Android and iOS, root detection requires platform-specific implementations.

Why detect root/jailbreak?

  • Stop unauthorised entry to app knowledge.
  • Mitigate tampering with app logic.
  • Adjust to safety requirements (e.g., banking apps).

Root detection in Android

Root detection in Android may be applied utilizing varied checks:

Pattern implementation (Android)

override enjoyable isDeviceRooted(): Boolean  checkForRWPaths() 
 
   non-public enjoyable checkForSuBinary(): Boolean {
       val paths = arrayOf(
           "/system/app/Superuser.apk",
           "/sbin/su",
           "/system/bin/su",
           "/system/xbin/su",
           "/knowledge/native/xbin/su",
           "/knowledge/native/bin/su",
           "/system/sd/xbin/su",
           "/system/bin/failsafe/su",
           "/knowledge/native/su",
           "/su/bin"
       )

 non-public enjoyable checkForRootPackages(): Boolean {
       val packages = arrayOf(
           "com.noshufou.android.su",
           "com.thirdparty.superuser",
           "eu.chainfire.supersu",
           "com.koushikdutta.superuser",
           "com.zachspong.temprootremovejb",
           "com.ramdroid.appquarantine"
       )
 
       return packages.any { packageName ->
           attempt {
               val pm = context.packageManager
               pm.getPackageInfo(packageName, 0)
               true
           } catch (e: Exception) {
               false
           }
       }
   }
}

 

Jailbreak detection in iOS

iOS jailbreak detection may be carried out utilizing:

  • Checking for the existence of Cydia or different jailbreak apps like Sileo or Zebra.
  • Checking for writable entry to system directories, akin to /non-public.
  • Trying to execute shell instructions, that are usually restricted.

Pattern implementation (iOS) [Platform.ios.kt]

 override val jailbreakDetectionResult: JailbreakDetectionResult
        get() = checkJailbreak()

    non-public enjoyable checkJailbreak(): JailbreakDetectionResult {
        val jailbreakPaths = mapOf(
            "/Functions/Cydia.app" to "Cydia app detected",
            "/Library/MobileSubstrate/MobileSubstrate.dylib" to "MobileSubstrate detected",
            "/bin/bash" to "Bash shell detected",
            "/usr/sbin/sshd" to "SSH daemon detected",
            "/and so on/apt" to "APT bundle supervisor detected"
        )
}

2. SSL pinning

SSL pinning prevents man-in-the-middle (MITM) assaults by making certain that solely trusted certificates are accepted, even when an attacker has put in a customized certificates authority (CA) on the machine.

SSL pinning in Android

Android makes use of OkHttpClient with a customized certificates pinning configuration.

Certificates pinning logic

val certificatePinner = CertificatePinner.Builder()
       .add(hostname, “sha256/47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=”) // Unique pin
       .add(hostname, “sha256/Cl7dc6nofBuxRWuGgnZc9Fi/VYDPg608JSN91g/wQXA=”)
// Your pin
   .add(hostname, “sha256/wMSCtagZr+ada2dTKz2S7x2fU6YgXGn/a9pBqyEHu7U=”) // Burp Pin    
   .construct()

  • CertificatePinner: Specifies the legitimate certificates fingerprints for the server hostname. If the server certificates doesn’t match these fingerprints, the connection will fail.
  • Hostname: jsonplaceholder.typicode.com.
  • Pins: The SHA-256 hashes of legitimate server certificates.

Making the API request

val shopper = OkHttpClient.Builder()
          .certificatePinner(certificatePinner)
         .construct()

val request = Request.Builder()
        .url(“https://$hostname/customers“)
       .construct()

val response = shopper.newCall(request).execute()

  • OkHttpClient: Configured with the certificates pinning logic.

  • Request: A easy HTTP GET request to fetch consumer knowledge.

  • Response: Captures the response physique as a string.

 

SSL pinning in iOS

In iOS, SSL pinning is often applied utilizing a customized URLSessionDelegate that intercepts and validates server belief throughout community requests.

Beneath is a real-world implementation that mixes SSL pinning with proxy detection. This ensures the app not solely trusts particular certificates but in addition terminates execution if a community proxy is detected (a typical technique utilized by attackers to intercept visitors).

Pattern implementation (iOS)

static let shared = BlockProxyAndSSLPinning()
   non-public let pinnedKey = "sha256/47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=" // jsonplaceholder.typicode.com
   static func setup() {
       // 1. Test for proxy instantly
       if hasProxy() {
           fatalError("Proxy detected! Disable proxy to make use of the app.")
       }
       // 2. Configure SSL pinning for all requests
       URLProtocol.registerClass(BlockAllRequestsProtocol.self)
   }
   static func hasProxy() -> Bool {
       guard let settings = CFNetworkCopySystemProxySettings()?.takeRetainedValue() as? [String: Any] else {
           return false
       }
       return !(settings["HTTPProxy"] as? String ?? "").isEmpty
   }
   // SSL Pinning Validation
   func validate(problem: URLAuthenticationChallenge) -> Bool {
       guard let belief = problem.protectionSpace.serverTrust else { return false }

       // Confirm certificates
       var error: CFError?
       guard SecTrustEvaluateWithError(belief, &error) else { return false }
       // Get server's public key
       guard let serverKey = SecTrustCopyKey(belief),
             let keyData = SecKeyCopyExternalRepresentation(serverKey, nil) else {
           return false
       }
       // Calculate SHA256
       let knowledge = keyData as Knowledge
       var hash = [UInt8](repeating: 0, depend: Int(CC_SHA256_DIGEST_LENGTH))
       knowledge.withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(knowledge.depend), &hash) }
       let serverKeyHash = "sha256/" + Knowledge(hash).base64EncodedString()

       return serverKeyHash == pinnedKey
   }
}

SSL pinning logic

  • Makes use of SecTrustEvaluateWithError() to confirm the server’s certificates.

  • Extracts the general public key from the certificates and hashes it utilizing SHA256.

  • Compares the ensuing hash with a predefined pinned worth (pinnedKey).

SSL pinning ensures your app solely trusts particular certificates, decreasing MITM danger.

Android SSL pinning instance (OkHttp3)

val certificatePinner = CertificatePinner.Builder()
    .add(hostname, "sha256/47DEQpj8HBSa+/TIm...") 
    .construct()

iOS SSL pinning with proxy detection

func validate(problem: URLAuthenticationChallenge) -> Bool { // confirm SSL certs & examine SHA256 hash }

Part 2: Bypass methods

Root/Jailbreak detection bypass methods

 

1. Bypassing root/jailbreak detection with Frida

Frida is a strong dynamic instrumentation instrument that permits attackers to hook into working purposes and modify their behaviour at runtime.

Steps to bypass root detection utilizing Frida

1. Begin the Frida server on the machine
adb push frida-server /knowledge/native/tmp/
adb shell chmod 755 /knowledge/native/tmp/frida-server
adb shell ./knowledge/native/tmp/frida-server &

image (4)-1

2. Connect Frida to the goal utility
frida -U -n com.instance.kmm_test -e "console.log('Frida connected');"

image (5)

3. Run a Frida script to override root detection features
Java.carry out(operate() {
    var rootCheck = Java.use("com.instance.kmm_test.RootDetector");
    rootCheck.isDeviceRooted.implementation = operate() {
        console.log("Bypassing root detection");
        return false;
    };
});

2. Bypassing root/jailbreak detection with Objection

Objection is a runtime cell exploitation framework constructed on Frida, permitting safety researchers to bypass safety mechanisms simply.

Steps to bypass root/jailbreak detection utilizing Objection

1. Connect Objection to the app
objection -g com.instance.kmm_test discover
2. Disable root detection
android root disable

image (6)-1

Efficiently bypassed ✅

image (7)-2

3. Disable jailbreak detection
ios jailbreak disable

image (8)

Efficiently bypassed ✅

image (9)

Bypassing root/jailbreak detection at a look

 

Instrument

Platform

Technique

Final result

Frida

Android/iOS

Hook root/jailbreak checks

Rooted machine seems “protected”

Objection

Each

Disable detection at runtime

Bypasses checks immediately

SSL pinning bypass methods

SSL pinning ensures that solely particular certificates are trusted by the appliance, stopping Man-in-the-Center (MITM) assaults. Attackers usually attempt to bypass SSL pinning to intercept and modify API requests.

1. Bypassing SSL pinning with Frida

If you attempt the objection instrument to bypass SSL pinning, you’ll get error messages and won’t be able to bypass.

image (10)

Not capable of bypass utilizing Objection ❌

image (11)-1

Now we use a Frida script to bypass SSL pinning and goal a specific OkHttp3 operate and alter the return worth.

Steps to bypass SSL pinning

 

1. Begin the Frida server
adb shell ./knowledge/native/tmp/frida-server &
2. Use an SSL pinning bypass script
frida -U -f org.instance.challenge -e "
Java.carry out(operate () {
    attempt {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');

        // Hook the overloaded technique: verify$okhttp(String, Function0)
        CertificatePinner.verify$okhttp.overload('java.lang.String', 'kotlin.jvm.features.Function0').implementation = operate (host, certChainCleaner) {
            console.log('[+] Bypassing OkHTTPv3 CertificatePinner verify$okhttp');
            console.log('    Host: ' + host);
            // You'll be able to return with out throwing any exceptions to bypass the verify
            return;
        };

        console.log('[*] OkHTTPv3 pinning bypass hooked efficiently');
    } catch (err) {
        console.log('[!] Exception: ' + err.message);
    }
}); "

This Frida script is designed to bypass SSL pinning in Android purposes that use OkHttp3. Particularly, it targets the CertificatePinner class and hooks the verify$okhttp technique, which is liable for validating the server’s SSL certificates towards a predefined pin. 

By overriding this technique’s implementation, the script ensures that no exceptions are thrown throughout certificates validation, successfully disabling the pinning mechanism. This enables visitors interception instruments like Burp Suite to examine HTTPS visitors with out being blocked by certificates mismatches. Using Frida allows this modification dynamically at runtime with out the necessity to recompile the APK.

image (12)

Efficiently bypassed SSL pinning ✅

image (13)

2. Bypassing SSL pinning with Objection for iOS

Steps to bypass SSL pinning

 

1. Connect Objection to the app
objection -g com.instance.kmm_test discover
2. Disable SSL pinning in iOS
ios sslpinning disable

Efficiently bypassed iOS SSL pinning

image (14)

Bypassing SSL pinning at a look

 

Instrument

Platform

Technique

Final result

Frida

Android

Hook CertificatePinner

Disables SSL checks

Objection

iOS

Command: ios sslpinning disable

SSL pinning bypassed

Fast comparability: Implementation vs. bypass

 

Mechanism

Implementation technique

Widespread bypass instruments

Mitigation

Root/Jailbreak detection

System checks (binaries, directories, packages)

Frida, Objection

Obfuscation, RASP

SSL pinning

Certificates hash verification

Frida, Objection

Dynamic pinning, Cert transparency logs

Greatest practices: Staying forward of attackers

✅ Mix root/jailbreak detection + SSL pinning for layered protection

✅ Frequently replace detection logic towards new bypass scripts

✅ Use runtime utility self-protection (RASP) for stronger enforcement

✅ At all times conduct penetration testing earlier than app releases

Conclusion

KMM streamlines cross-platform cell growth, however sturdy safety relies on platform-specific implementations. Root detection and SSL pinning are important instruments in your defence arsenal, however they have to be applied rigorously and constantly up to date.

Whereas no system is foolproof, layering safety features and understanding how attackers bypass them places you a step forward.

🚧 “Defence isn’t simply constructing partitions, it’s figuring out the place attackers climb them.”

Keep safe and at all times take a look at your apps like an attacker would!

💡Remaining tip: At all times conduct penetration testing to determine vulnerabilities earlier than attackers do!

Incessantly requested questions (FAQs)

 

1. Is SSL pinning foolproof?

No. Attackers can nonetheless bypass with Frida or Objection. That’s why layered safety and steady testing are important.

2. Do all apps want jailbreak/root detection?

Not all apps want jailbreak/root detection, however apps dealing with delicate knowledge (banking, fintech, healthcare) ought to implement it.

3. What’s one of the simplest ways to check my implementation?

Use instruments like Frida and Objection your self throughout penetration testing to validate defenses and take a look at your implementation.



LEAVE A REPLY

Please enter your comment!
Please enter your name here