Mobile App Security: The Flaw That Exposed User Data
π The Discovery
I was reviewing a mobile app for a client. Routine security audit. Then I found something concerning.
The app was exposing user data. Not through a hackβthrough a simple configuration mistake.
The flaw: API keys and user data were stored in plaintext in the app bundle. Anyone could extract them.
π₯ What I Found
1. Hardcoded API Keys
The app had API keys hardcoded in the source code:
// Bad: Hardcoded API key
let apiKey = "sk_live_1234567890abcdef"
These keys were visible in the compiled app. Anyone could extract them.
2. User Data in Logs
The app logged sensitive data:
// Bad: Logging sensitive data
print("User email: \(user.email)")
print("User token: \(user.authToken)")
Logs could be accessed by other apps or through device backups.
3. Unencrypted Local Storage
User data was stored unencrypted:
// Bad: Unencrypted storage
UserDefaults.standard.set(user.email, forKey: "user_email")
UserDefaults.standard.set(user.password, forKey: "user_password")
4. No Certificate Pinning
The app didn't pin SSL certificates, making it vulnerable to man-in-the-middle attacks.
β How to Fix
1. Use Environment Variables
Store API keys in environment variables, not code:
// Good: Environment variable
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
2. Use Keychain
Store sensitive data in Keychain (iOS) or Keystore (Android):
// Good: Keychain storage
let keychain = Keychain(service: "com.app.credentials")
try keychain.set(user.password, key: "user_password")
3. Encrypt Local Data
Encrypt data before storing locally:
// Good: Encrypted storage
let encrypted = try AES256.encrypt(user.email, key: encryptionKey)
UserDefaults.standard.set(encrypted, forKey: "user_email")
4. Certificate Pinning
Pin SSL certificates to prevent MITM attacks:
// Good: Certificate pinning
let certificates = try loadCertificates()
let evaluator = PinnedCertificatesTrustEvaluator(certificates: certificates)
let manager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(evaluators: ["api.example.com": evaluator]))
5. Remove Debug Logs
Don't log sensitive data in production:
// Good: Conditional logging
#if DEBUG
print("User email: \(user.email)")
#endif
π Impact
What was exposed:
- API keys (could be used to access backend)
- User emails and passwords
- Authentication tokens
- Personal information
Risk level: Critical
π‘ Prevention Checklist
- β Never hardcode API keys
- β Use Keychain/Keystore for sensitive data
- β Encrypt local storage
- β Implement certificate pinning
- β Remove debug logs from production
- β Use obfuscation for sensitive code
- β Regular security audits
π― Key Takeaways
- Mobile apps can expose data through simple mistakes
- Never hardcode secrets in apps
- Use secure storage (Keychain/Keystore)
- Encrypt sensitive data
- Implement certificate pinning
- Regular security audits are essential
This flaw was easy to fix, but it could have exposed thousands of users' data. Security should be built in from the start, not added later.