Sem 7

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

ApproachWhat the tester knowsHow it works
Black boxNothing about the source code or internalsGive 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 boxThe source codeWalk 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).

  1. Intercept the request from the mobile app.
  2. Find the URL of the web service it calls.
  3. 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

AppType
DIVA (Damn Insecure and Vulnerable App)Standalone
InsecureBankv2Client-server (Santoku, Genymotion)
OWASP GoatDroidBanking, 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 2016OWASP 2024Change
M1Improper Platform UsageImproper Credential UsageNew
M2Insecure Data StorageInadequate Supply Chain SecurityNew
M3Insecure CommunicationInsecure Authentication / AuthorizationMerged M4 and M6 into M3
M4Insecure AuthenticationInsufficient Input/Output ValidationNew
M5Insufficient CryptographyInsecure CommunicationMoved from M3 to M5
M6Insecure AuthorizationInadequate Privacy ControlsNew
M7Client Code QualityInsufficient Binary ProtectionsMerged M8 and M9 into M7
M8Code TamperingSecurity MisconfigurationRewording of M10
M9Reverse EngineeringInsecure Data StorageMoved from M2 to M9
M10Extraneous FunctionalityInsufficient CryptographyMoved 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 ID

Each 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.Log class.
  • Apps read log output with the logcat command.
MethodLevel
Log.ddebug
Log.eerror
Log.iinfo
Log.vverbose
Log.wwarn

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_LOGS in its manifest.
  • Before Android 4.0, any app with READ_LOGS could read all other apps' log output.
  • From Android 4.1, the meaning of READ_LOGS changed. 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

  1. Install DIVA (adb install or drag and drop).
  2. Open it in JADX. Read the LogActivity class. It calls Log.e and logs the credit card number with the error message.
  3. In the Genymotion shell, find DIVA's PID with ps -A | grep "diva".
  4. Enter input in DIVA challenge 1.
  5. Read the log for that PID.
logcat | grep "<pid of diva>"       # inside the shell (Santoku)
adb logcat | grep "<pid of diva>"   # from the PC

The 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.e and 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

  1. Enter a random value. Access is denied.
  2. Open the activity's Java class in JADX.
  3. 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

  1. Enter credentials and save.
  2. The Java class uses SharedPreferences and does not encrypt the username or password.
  3. 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 text

Apps 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_PRIVATE is a constant in android.content.Context. It is the mode parameter of getSharedPreferences() or openOrCreateDatabase().
  • 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

  1. Enter credentials.
  2. The class stores them in a SQLite database named ids2.
  3. 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 text

Encrypt 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

  1. Check the app folder first: cd /data/data/jakhar.aseem.diva, ls. No temp file yet; it is created only after credentials are entered.
  2. Enter credentials in the app.
  3. The code shows a temp file being created.
  4. List the same folder again. The file is now there.
  5. cat it 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_STORAGE to write to any external file of any app.

Demo (challenge 6)Search on YouTube

  1. Allow DIVA to write to storage: Settings, Privacy, Permission manager, Files, allow DIVA.
  2. The source code writes a file to external storage.
  3. Read it:
cd /mnt/sdcard
ls -al              # -a shows hidden files
cat .uinfo.txt      # username and password

Keep 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

  1. Enter a website such as http://gmail.com. It loads.
  2. Create a text file with some content and save it in the emulator's Download folder.
  3. In challenge 8, enter:
file:///mnt/sdcard/Download/test.txt

The 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

  1. In the manifest, find the activity jakhar.aseem.diva.AccessControl1Activity.
  2. It opens another activity through an intent filter with the action jakhar.aseem.diva.action.VIEW_CREDS.
  3. Start that activity directly with adb:
adb shell
am start -a jakhar.aseem.diva.action.VIEW_CREDS

The 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

  1. In JADX, analyse the manifest. Find AccessControl2Activity and check its intent filter.
  2. Invoke it:
am start -a jakhar.aseem.diva.action.VIEW_CREDS2
  1. It asks for a PIN. So it looks protected.
  2. Read the source. It checks a Boolean extra.
  3. In JADX, open res/values/strings.xml. The exact name of the extra is check_pin.
  4. Pass the extra with value false:
am start -a jakhar.aseem.diva.action.VIEW_CREDS2 --ez "check_pin" false

The 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

  1. In the manifest, locate the provider jakhar.aseem.diva.NotesProvider and its activities.
  2. The activity code contains goToNotes().
  3. In NotesProvider.class, find the content URI (content://...).
  4. Query it with adb:
adb shell content query --uri content://jakhar.aseem.diva.provider.notesprovider/notes

The 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, use grantUriPermission() for per-URI sharing, and enforce checks inside query, insert and delete.
  • 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

  1. The activity's source uses JNI. It compares the input with a string from another (native) source file.
  2. Find the native library on the device:
cd /data/data/jakhar.aseem.diva
ls              # a lib directory holds the native code
cd lib
ls
  1. The library is also in JADX's output under resources/lib/arm64-v8a.
  2. List its readable strings and guess which one is the vendor key:
strings libdivajni.so | less
  1. The source is divajni.c in the payatu/diva-android GitHub 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

  1. Enter input longer than the allocated size. The app crashes.
  2. Read the logs:
adb logcat | grep "<pid of diva>"     # shows size exceeded errors

The 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 with logcat | grep <pid>; fix with a custom log class.
  • Insecure storage: shared_prefs XML, ids2 database, temp files, .uinfo.txt on SD card; fix with MODE_PRIVATE, encryption and Android Keystore.
  • Input validation: SQLi ' or '1'='1, WebView file:// access, DoS by oversized input.
  • Access control: am start -a ... VIEW_CREDS, --ez "check_pin" false, and content query --uri on an exported provider.
  • Hardcoded keys hide in Java code or native .so libraries (strings libdivajni.so).