- by x32x01 ||
In Android app security, reverse engineering helps you spot common mistakes developers make-especially mistakes that can expose secrets, enable XSS in WebView, or leak sensitive data through resources and databases 🕵️♂️📱.
This guide breaks down what to look for when reviewing an APK, using examples inspired by vulnerable training apps like InjuredAndroid.
Example in Java:
Example in layout:
Then in strings.xml:
✅ Helpful for maintenance
⚠️ Dangerous when developers store API keys, secrets, tokens there.
Red flags include:
✅ Defensive fix ideas (high level):
Common signs:
What to look for:
You may see patterns like:
Red flags:
Security problems happen when developers store:
Common places to find references:
This guide breaks down what to look for when reviewing an APK, using examples inspired by vulnerable training apps like InjuredAndroid.
Understanding Default Android Files 📂✅
Before hunting bugs, you need to know the “default files” you’ll see in almost every APK.AndroidManifest.xml 🧾
The manifest is like the app’s blueprint. It tells Android what the app can do and what it needs to run. Common things it declares:- Permissions the app requests (camera, storage, internet, etc.) 🔐
- Activities (app screens) and exported components
- Intent filters (what links/actions the app can handle) 🔗
- Data schemes (like custom deep links)
- SDK versions the app supports 📌
- Input and configuration settings
strings.xml 🧩
This file stores text values the app can reuse anywhere (Java/Kotlin + layouts). Instead of hardcoding text, devs reference it using resource IDs.Example in Java:
Java:
String s = getString(R.string.hello); Example in layout:
XML:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/hello" /> XML:
<resources>
<string name="hello">Hello!</string>
</resources> ⚠️ Dangerous when developers store API keys, secrets, tokens there.
R.java (Generated) ⚙️
R.java is auto-generated and contains IDs for everything inside res/ (layouts, strings, drawables). It gets regenerated automatically and is mainly used by the app to reference resources.
Spotting Improper WebView Implementation 🌐⚠️
A common Android security issue is an insecure WebView setup.Red flags include:
- Loading user input into WebView as HTML
- Enabling JavaScript without strict controls
- Using weak URL validation or allowing arbitrary content
- App takes input from a text field
- Passes it via Intent to another Activity
- That Activity renders it inside WebView using HTML parsing
✅ Defensive fix ideas (high level):
- Avoid rendering raw user content as HTML
- Disable JavaScript unless absolutely required
- Use proper encoding/sanitization
- Restrict navigation and enforce safe URLs
Hardcoded Secrets in Code 🔑😬
Developers sometimes hardcode secrets for “convenience”-like flags, API keys, or login comparisons.Common signs:
- A login function compares input to a hardcoded value
- “Secret” strings appear inside suspicious methods
- Obfuscation exists, but logic is still readable
- Reverse engineering can reveal the “correct value”
- Authentication checks can be bypassed
- Secrets can be extracted quickly
- Never store secrets in the client app
- Use server-side validation and short-lived tokens
Secrets Hidden in strings.xml 🧠📌
Even when secrets aren’t in code, devs often store them instrings.xml and reference them through R.string.something.What to look for:
- Weird looking string keys (random names)
- Base64-like chunks
- Anything that looks like tokens, keys, or credentials
- Don’t store secrets in
strings.xml - If you must store configuration, keep it non-sensitive and rotate keys server-side
Insecure Class Implementations 🧱🚩
Sometimes secrets aren’t stored in plain strings-they’re returned from helper classes.You may see patterns like:
- Activity calls a method from a helper class
- Helper decodes something (Base64, hex, etc.)
- The return value is compared with user input
- decode → transform → return → compare
- Avoid client-side “secret checking”
- Do validation and sensitive logic on the server
Weak Decryption for Hardcoded Values 🔓🧨
Another classic issue: apps include custom decryption logic (sometimes using old algorithms) to “hide” secrets.Red flags:
- Old crypto like DES
- Hardcoded keys inside the app
- Base64 + decrypt pattern
- DIY crypto utilities
- If the app can decrypt it, attackers can too
- Hardcoded keys make encryption meaningless
- Use modern crypto (AES/GCM) where appropriate
- Don’t hardcode keys
- Prefer server-side secrets and key management
Insecure Cryptography in SQLite Databases 🗄️⚠️
Android apps often use SQLite to store data locally.Security problems happen when developers store:
- Passwords
- API tokens
- Keys
- Sensitive user info
- Weak hashing (like MD5)
- Weak encoding/“encryption” (like ROT variants)
- No encryption at all
- Avoid storing secrets locally
- Use strong hashing (bcrypt/Argon2) for passwords (server-side)
- Use Android Keystore + encrypted storage for sensitive data
Hardcoded AWS Credentials ☁️🚫
One of the most dangerous mistakes is embedding cloud credentials in the mobile app.Common places to find references:
strings.xml- build config files
- code where SDK clients are initialized
- Leaked cloud keys can expose buckets, databases, logs, and more
- Attackers may use them outside the app
- Never ship long-term AWS keys in a client app
- Use temporary credentials (STS), IAM roles, or server-issued tokens
- Restrict permissions (least privilege) and monitor usage
Conclusion ✅🛡️
Even with obfuscation, many apps still leak sensitive data through:- WebView misconfigurations
- Hardcoded secrets
- strings.xml references
- insecure helper classes
- weak crypto patterns
- exposed SQLite data
- embedded cloud credentials
Last edited: