The screen brightness was burning my eyes, it was 03:14 AM, and I was watching the endless stream of adb logcat output on my terminal. Something was off with the beta version of testCompany's new mobile payment app. The app was sending unencrypted data to a weird background endpoint (http://api.example.com/v1/debug/dump) without any user consent. Worse, that data contained the unmasked version of the user's last used credit card. I took a sip of my cold coffee and reached for the keyboard; I knew right then I had to fix this before the sun came up.
First Step: Infiltrating the Castle from the Back Door (Decompiling)
When we talk about mobile security, most people just think about setting a passcode or checking for 'Root/Jailbreak' status. But the kitchen is much wilder than that. First thing I did was grab the APK file. When I dove in with jadx-gui, the view was painful: the development team had pushed a 'Logger' class to production that was forgotten in debug mode. On top of that, the app hadn't been through any 'obfuscation' (code hardening). Everything was laid bare.
Sometimes, just opening the APK and looking at strings.xml or the AndroidManifest.xml file can spill all of an app's secrets. I ran into something like this:
<!-- Snippet from AndroidManifest.xml -->
<activity android:name=".WebViewActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="testcompany-app" android:host="payment" />
</intent-filter>
</activity>
That testcompany-app://payment is a Deep Link. If you don't design the parameters of this link correctly, an attacker could trigger any action they want inside the app via a simple SMS or email sent to the user. For example: testcompany-app://payment?amount=1000&to=attacker_account. If the app processes this parameter without validation, it's game over.
SSL Pinning: Security or Illusion?
If you meet someone who says, "We use SSL Pinning, no one can intercept our traffic," tell them about Frida. When I tried to listen to the traffic between the app and the server using Burp Suite, the app rejected the connection. Nice, at least there was a certificate check. But for a Red Teamer, that's just a 5-minute hurdle.
Using Frida, I manipulated the function responsible for the certificate check (like TrustManager) at runtime. Here is the logic of that famous bypass script (defanged/pseudo-code):
// Frida script to bypass SSL Pinning
Java.perform(function () {
var array_list = Java.use("java.util.ArrayList");
var ApiClient = Java.use("com.testcompany.app.network.ApiClient");
ApiClient.checkServerTrusted.implementation = function (chain, authType) {
// Do nothing when the function is called and return without error
console.log("[+] SSL Pinning bypassed!");
return;
};
});
