Ah, youthful enthusiasm... In my first mobile pentest, when I was still very green, I dove deep into a banking app. Our target was a new wallet application for a firm called testCompany. Back then, I was trying to do everything manually, basically thinking I was Neo from 'The Matrix'. I decompiled the app, got lost in Smali code for hours, and finally had that famous 'Eureka!' moment. I claimed I’d found an API key that would give me keys to the kingdom. I told the team, 'Found it guys, we’re in!'
But there was one tiny detail: The key I found was actually just a public, unrestricted Google Maps API key used for showing branch locations. That day, I learned that just finding something isn't enough; knowing what, where, and why you found it—understanding the context—is everything. Since then, I go into every mobile project thinking, 'Alright, let's see where we’re going to trip up this time?'
Decompiling? That's the Easy Part!
When we start a Red Team engagement, usually the first thing we do is grab the APK or IPA file and tear it apart. In the Android world, this is child's play with jadx-gui or apktool. But the point isn't just reading the code; it's finding that little 'moment of forgetfulness' a developer left behind on a tired Tuesday evening.
My favorite type of mistake is finding API keys embedded inside strings.xml or hardcoded directly into Java/Kotlin code. My developer friends often say, 'Well, this app becomes a binary, nobody can see my code.' Oh buddy, decompiling takes literally seconds.
Look at this, for example—it's so common it hurts:
// Defanged example
public class ApiConfig {
private static final String API_KEY = "sk_test_51Mz9...THIS_IS_A_MOCK_KEY..."; // DANGER!
private static final String BASE_URL = "https://api.example.com/v1/";
}
At this point, you have to think: If this key falls into the hands of a Red Teamer, what kind of permissions does it have on the backend? If this is a payment system and that key points to 'live' instead of 'test', it's game over.
Local Storage: The Black Hole We Think Is Safe
Apps love storing data. User preferences, session tokens, and sometimes (unfortunately) user passwords... On Android, it's SharedPreferences; on iOS, it's UserDefaults; or SQLite databases on both.
There’s a mistake that hasn't changed in years: storing sensitive data in plain-text. The developer thinks, 'I'm storing this in the app's private area, other apps can't touch it.' On a rooted device or against an attacker with physical access, that 'private area' protection is just an illusion.
For instance, check out this innocent-looking line in an AndroidManifest.xml file:
<application
android:allowBackup="true"
... >
</application>
This line allows an attacker to pull all the app's data to their computer using a simple adb backup command. Even if your phone has a passcode, if the attacker gets their hands on the device while it's unlocked (or uses other tricks), they can extract your local databases and preferences in seconds.
Remember: if it's sensitive, it needs to be in the Keychain (iOS) or Keystore (Android), and it definitely shouldn't be backed up in plain sight.
