DIVA App Vulnerabilities
Covers the deck DIVA App: black box and white box mobile pentesting, sample vulnerable apps, OWASP Mobile Top 10 (2016 vs 2024), and the 13 DIVA challenges (insecure logging, hardcoding, insecure storage, SQL injection, WebView abuse, access control, leaking content providers, JNI, DoS) with demo commands and fixes.
Mobile App Pentesting StrategySearch on YouTube
| Approach | What the tester knows | How it works |
|---|---|---|
| Black box | Nothing about the source code or internals | Give valid and invalid input and watch the response. Send payloads (for example SQL injection) through input controls such as text boxes, as part of the URL, or inside any string or variable by intercepting the request. Mostly used for web apps when source is unavailable; also possible for Android apps. |
| White box | The source code | Walk through the source to understand the app. Possible for mobile apps because the APK can be reverse engineered to get the source. |
Web application security meets mobile application securitySearch on YouTube
Many mobile apps talk to a web server (web service, application framework, web application, database engine, third-party APIs).
- Intercept the request from the mobile app.
- Find the URL of the web service it calls.
- Paste that URL in a web browser. The request reaches the web application.
From here the test becomes a web application pentest.
Sample Vulnerable Android AppsSearch on YouTube
| App | Type |
|---|---|
| DIVA (Damn Insecure and Vulnerable App) | Standalone |
| InsecureBankv2 | Client-server (Santoku, Genymotion) |
| OWASP GoatDroid | Banking, social network; client-server |
Security pentesting tools and methodsSearch on YouTube
- Manual testing through interface interception
- Burp Suite (proxy to intercept and modify traffic)
- Drozer (comprehensive security and attack framework for Android)
- MobSF (Mobile Security Framework, automated static and dynamic analysis)
- OWASP Mobile Top 10 as the checklist
OWASP Mobile Top 10: 2016 vs 2024Search on YouTube
| # | OWASP 2016 | OWASP 2024 | Change |
|---|---|---|---|
| M1 | Improper Platform Usage | Improper Credential Usage | New |
| M2 | Insecure Data Storage | Inadequate Supply Chain Security | New |
| M3 | Insecure Communication | Insecure Authentication / Authorization | Merged M4 and M6 into M3 |
| M4 | Insecure Authentication | Insufficient Input/Output Validation | New |
| M5 | Insufficient Cryptography | Insecure Communication | Moved from M3 to M5 |
| M6 | Insecure Authorization | Inadequate Privacy Controls | New |
| M7 | Client Code Quality | Insufficient Binary Protections | Merged M8 and M9 into M7 |
| M8 | Code Tampering | Security Misconfiguration | Rewording of M10 |
| M9 | Reverse Engineering | Insecure Data Storage | Moved from M2 to M9 |
| M10 | Extraneous Functionality | Insufficient Cryptography | Moved from M5 to M10 |
DIVA Lab SetupSearch on YouTube
The demos use DIVA (package jakhar.aseem.diva) on a Genymotion emulator, with Santoku as the analyst machine and JADX to read the decompiled Java code.
adb install <diva>.apk # or drag and drop the APK onto the emulator
adb shell # shell on the emulator
ps -A | grep "diva" # find the DIVA process IDEach challenge follows the same pattern: use the app, read the matching class in JADX, then find the leaked data on the device.
1. Insecure LoggingSearch on YouTube
Rule: do not log sensitive information.
- The phone logs everything the app does: calling activities, intents and so on.
- Apps send output to the log with the
android.util.Logclass. - Apps read log output with the
logcatcommand.
| Method | Level |
|---|---|
Log.d | debug |
Log.e | error |
Log.i | info |
Log.v | verbose |
Log.w | warn |
Bad examples from the slide:
Log.v("method", Login.TAG + ",account=" + str1);
Log.v("method", Login.TAG + ",password=" + str1);READ_LOGS permission historySearch on YouTube
- An app that wants other apps' logs declares
READ_LOGSin its manifest. - Before Android 4.0, any app with
READ_LOGScould read all other apps' log output. - From Android 4.1, the meaning of
READ_LOGSchanged. Even with it, apps cannot read other apps' logs. - But a PC connected to the device can still read log output from all apps.
DemoSearch on YouTube
- Install DIVA (
adb installor drag and drop). - Open it in JADX. Read the
LogActivityclass. It callsLog.eand logs the credit card number with the error message. - In the Genymotion shell, find DIVA's PID with
ps -A | grep "diva". - Enter input in DIVA challenge 1.
- Read the log for that PID.
logcat | grep "<pid of diva>" # inside the shell (Santoku)
adb logcat | grep "<pid of diva>" # from the PCThe credit card details appear next to the error.
- Never send sensitive data to log output.
- If the app uses a third-party library or API, make sure it does not log sensitive data either.
- Common solution: declare and use a custom log class instead of calling
Log.v,Log.eand so on directly. Logging can then be switched off in release builds.
2. Hardcoding IssuesSearch on YouTube
Hardcoding is putting confidential data (passwords, access tokens, authentication strings) directly in the source code as a constant, for simplicity.
Demo (challenge 2)Search on YouTube
- Enter a random value. Access is denied.
- Open the activity's Java class in JADX.
- The check compares the input with a hardcoded string. That string is the key. Enter it and access is granted.
Do not keep secrets in code or in res/values. Anyone can decompile the APK. Keep keys on the server, or protect them with the Android Keystore.
3. Insecure Data Storage: Shared PreferencesSearch on YouTube
Developers may store sensitive data without encryption in:
- Shared preferences (
/data/data/<package name>/) - Databases
- Temporary files
- External storage
In Android, data moves through intents, is written to files, is shared through shared preferences or is stored in databases.
Some Developers Trust Everything
The four insecure storage spots (DIVA challenges 3 to 6): Shared preferences, Database, Temporary file, External storage.
Demo (challenge 3)Search on YouTube
- Enter credentials and save.
- The Java class uses SharedPreferences and does not encrypt the username or password.
- Read the file on the device.
adb shell
cd /data/data/jakhar.aseem.diva
ls
cd shared_prefs
ls # find the .xml file
cat <file>.xml # username and password in plain textApps that call third-party APIs must pass authentication tokens. Developers often store these tokens in shared preferences too.
- Encrypt such data, or store it with
MODE_PRIVATE. MODE_PRIVATEis a constant inandroid.content.Context. It is the mode parameter ofgetSharedPreferences()oropenOrCreateDatabase().- Use the Android Keystore (secured by the TEE). The API token is stored encrypted in app storage, and its encryption key is protected by the Keystore.
4. Insecure Data Storage: DatabaseSearch on YouTube
This is not an issue for web apps, because there the database sits on the web server. On mobile it sits on the device.
Demo (challenge 4)Search on YouTube
- Enter credentials.
- The class stores them in a SQLite database named
ids2. - Read the database.
cd /data/data/jakhar.aseem.diva/databases
ls # ids2 is listed
sqlite3 ids2 # sqlite3 is available in Santoku
.tables
select * from myuser; # username and password in plain textEncrypt sensitive columns (or the whole database) with a key kept in the Android Keystore. Do not store passwords in plain text.
5. Insecure Data Storage: Temporary FileSearch on YouTube
Developers may create temporary files on the SD card or in internal storage.
Demo (challenge 5)Search on YouTube
- Check the app folder first:
cd /data/data/jakhar.aseem.diva,ls. No temp file yet; it is created only after credentials are entered. - Enter credentials in the app.
- The code shows a temp file being created.
- List the same folder again. The file is now there.
catit to see the username and password.
6. Insecure Data Storage: External Storage (SD Card)Search on YouTube
- The SD card is readable even without rooting the phone.
- Android lets apps save persistent data in external storage (
/mnt/sdcard). - Before Android 4.1, external storage was world-readable.
- From Android 1 to 4.3, an app needed only
WRITE_EXTERNAL_STORAGEto write to any external file of any app.
Demo (challenge 6)Search on YouTube
- Allow DIVA to write to storage: Settings, Privacy, Permission manager, Files, allow DIVA.
- The source code writes a file to external storage.
- Read it:
cd /mnt/sdcard
ls -al # -a shows hidden files
cat .uinfo.txt # username and passwordKeep sensitive data in internal storage (MODE_PRIVATE), never on the SD card. Delete temporary files after use and encrypt anything that must be written.
7. Input Validation: SQL InjectionSearch on YouTube
Inputs may carry malicious content such as SQL queries. Input validation checks dangerous input so it is safe to process.
If the app does not validate input, an attacker crafts input the rest of the app does not expect. With SQL, the database engine runs the injected commands and may reveal confidential data.
SELECT * FROM employee WHERE user_id = '1';
-- input for user_id: X' or '1'='1
SELECT * FROM employee WHERE user_id = 'X' or '1'='1';
-- the condition is always true, so this is the same as:
SELECT * FROM employee WHERE true;Demo (challenge 7)Search on YouTube
Enter diva' or '1'='1 in the search box. All user details are returned. The flaw is in the search() method of SQLInjectionActivity, which builds the query by string concatenation.
Use parameterised queries (? placeholders with selectionArgs) instead of string concatenation. Validate and sanitise input against an allow list.
8. Input Validation: Abusing WebViewSearch on YouTube
A WebView loads a remote URL or shows HTML pages stored in the app, inside an activity. If input is not sanitised, a malicious string runs inside the app and may reveal sensitive data.
Demo (challenge 8)Search on YouTube
- Enter a website such as
http://gmail.com. It loads. - Create a text file with some content and save it in the emulator's Download folder.
- In challenge 8, enter:
file:///mnt/sdcard/Download/test.txtThe text file content is shown. This is abuse: the WebView is meant for web pages, but the text box can read sensitive local files.
Sanitise the URL. Allow only http or https schemes and block file://. Disable file access in the WebView (setAllowFileAccess(false)).
9. Access Control Issues (Part 1)Search on YouTube
Access control issues arise when:
- the app does not authenticate the user;
- an authorisation check is missing;
- an attacker with too little privilege can see a protected resource.
Demo: view API credentials without the buttonSearch on YouTube
- In the manifest, find the activity
jakhar.aseem.diva.AccessControl1Activity. - It opens another activity through an intent filter with the action
jakhar.aseem.diva.action.VIEW_CREDS. - Start that activity directly with adb:
adb shell
am start -a jakhar.aseem.diva.action.VIEW_CREDSThe credentials activity opens on the emulator.
10. Authentication Based Access Control (Part 2)Search on YouTube
- If not registered, the user must register and enter a PIN.
- If registered, the app assumes you already have a PIN, so that activity must be invoked.
DemoSearch on YouTube
- In JADX, analyse the manifest. Find
AccessControl2Activityand check its intent filter. - Invoke it:
am start -a jakhar.aseem.diva.action.VIEW_CREDS2- It asks for a PIN. So it looks protected.
- Read the source. It checks a Boolean extra.
- In JADX, open
res/values/strings.xml. The exact name of the extra ischeck_pin. - Pass the extra with value false:
am start -a jakhar.aseem.diva.action.VIEW_CREDS2 --ez "check_pin" falseThe credentials are shown. (--ez passes a Boolean extra with the intent.)
Set android:exported="false" on activities that other apps do not need. Do not trust intent extras for security decisions; check authentication inside the activity.
11. Access Control Part 3: Leaking Content ProvidersSearch on YouTube
- Content providers store and query data inside the app.
- Every content provider has a unique URI.
- If a content provider does not check authentication, other apps can query it like the authentic app.
Demo: read private notes without the PINSearch on YouTube
- In the manifest, locate the provider
jakhar.aseem.diva.NotesProviderand its activities. - The activity code contains
goToNotes(). - In
NotesProvider.class, find the content URI (content://...). - Query it with adb:
adb shell content query --uri content://jakhar.aseem.diva.provider.notesprovider/notesThe notes come back. The provider is not protected.
Solutions from the slide:
- If no cross-app sharing is needed, set
android:exported="false". Done. - If sharing is only with your own apps, create signature-level permissions and also check at runtime.
- If sharing with arbitrary apps occasionally, keep
exported="true"but require permissions, usegrantUriPermission()for per-URI sharing, and enforce checks insidequery,insertanddelete. - For sensitive data, encrypt with keys in the Android Keystore. Then even a leaked provider cannot reveal plaintext.
12. Hardcoding Part 2: Java Native InterfaceSearch on YouTube
The Java Native Interface (JNI) lets Java code in the VM interact with other libraries. Code in C and C++ can interact with Java through JNI.
The aim is to find the hardcoded vendor key. It may sit in a third-party native library, not in the Java source.
DemoSearch on YouTube
- The activity's source uses JNI. It compares the input with a string from another (native) source file.
- Find the native library on the device:
cd /data/data/jakhar.aseem.diva
ls # a lib directory holds the native code
cd lib
ls- The library is also in JADX's output under
resources/lib/arm64-v8a. - List its readable strings and guess which one is the vendor key:
strings libdivajni.so | less- The source is
divajni.cin thepayatu/diva-androidGitHub repo (app/src/main/jni/divajni.c).
13. Input Validation Part 3: Denial of ServiceSearch on YouTube
DoS happens when the user input is larger than the allocated memory. It overwrites memory fragments and crashes the app: stack overflow and heap overflow.
DemoSearch on YouTube
- Enter input longer than the allocated size. The app crashes.
- Read the logs:
adb logcat | grep "<pid of diva>" # shows size exceeded errorsThe developer must add a filter: check the input length before copying it into a fixed buffer.
DrozerSearch on YouTube
Drozer is a comprehensive security and attack framework for Android. It finds exposed activities, providers and services, similar to the manual adb tests above.
Quick self-testSearch on YouTube
Differentiate black box and white box mobile app testing.
Black box tests without the source: send valid and invalid input and payloads through the UI, URLs or intercepted requests. White box walks through the source code, which you get by reverse engineering the APK.
How did READ_LOGS change after Android 4.1?
Before 4.0, any app with READ_LOGS could read every app's logs. From 4.1, apps cannot read other apps' logs even with the permission. A connected PC still can.
Where does DIVA leak the credit card number, and how do you see it?
LogActivity logs it with Log.e. Find DIVA's PID with ps -A | grep "diva", then run logcat | grep <pid>.
Give the shell steps to read DIVA's shared preferences.
cd /data/data/jakhar.aseem.diva/shared_prefs, ls, then cat the XML file. Username and password are in plain text.
How do you dump the users from DIVA's database?
cd /data/data/jakhar.aseem.diva/databases, sqlite3 ids2, .tables, select * from myuser;.
What SQL injection input did the demo use, and why does it work?
diva' or '1'='1. The query becomes WHERE user_id='diva' or '1'='1', which is always true, so every row is returned.
How was the WebView abused?
Entering file:///mnt/sdcard/Download/test.txt made the WebView display a local file. The input was not restricted to web URLs.
Bypass the PIN in access control part 2.
am start -a jakhar.aseem.diva.action.VIEW_CREDS2 --ez "check_pin" false. The extra name check_pin comes from strings.xml.
How do you read a leaking content provider, and how is it fixed?
content query --uri content://jakhar.aseem.diva.provider.notesprovider/notes. Fix with exported="false", signature permissions, grantUriPermission() and permission checks in query, insert and delete, plus Keystore encryption.
How do you find a hardcoded key in a native library?
Go to the app's lib folder (or JADX resources/lib/arm64-v8a) and run strings libdivajni.so | less. Pick the likely key from the strings.
- Black box sends payloads through the UI or intercepted requests; white box reads reverse-engineered source.
- Practice apps: DIVA (standalone), InsecureBankv2 and GoatDroid (client-server); tools: Burp, Drozer, MobSF, OWASP Mobile Top 10.
- OWASP 2024 adds Improper Credential Usage (M1), Supply Chain (M2), Input/Output Validation (M4), Privacy Controls (M6); Insecure Data Storage moves to M9.
- Insecure logging leaks via
android.util.Log; read withlogcat | grep <pid>; fix with a custom log class. - Insecure storage: shared_prefs XML,
ids2database, temp files,.uinfo.txton SD card; fix withMODE_PRIVATE, encryption and Android Keystore. - Input validation: SQLi
' or '1'='1, WebViewfile://access, DoS by oversized input. - Access control:
am start -a ... VIEW_CREDS,--ez "check_pin" false, andcontent query --urion an exported provider. - Hardcoded keys hide in Java code or native
.solibraries (strings libdivajni.so).