deardaniel/secdata-raw huggingface dataset:
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0093

---
platform: android
title: Uses of Extended Validity Duration in setUserAuthenticationParameters with semgrep
id: MASTG-DEMO-0093
code: [kotlin]
test: MASTG-TEST-0330
---

## Sample

This sample demonstrates the insecure use of [`setUserAuthenticationParameters`](https://developer.android.com/reference/android/security/keystore/KeyGenParameterSpec.Builder#setUserAuthenticationParameters(int,%20int)) with an extended validity duration when generating cryptographic keys for biometric authentication.

When a key is configured with `setUserAuthenticationParameters(86400, type)` (86400 seconds = 24 hours), it remains unlocked for 24 hours after successful authentication. During this window misuse of the app can be a potential risk, for example in case physical access to the device is possible executing sensitive operations without re-authenticating through biometric verification.

{{ ../MASTG-DEMO-0090/MastgTest.kt # ../MASTG-DEMO-0090/MastgTest_reversed.java }}

## Steps

Let's run @MASTG-TOOL-0110 rules against the sample code.

{{ ../../../../rules/mastg-android-biometric-validity-duration.yml }}

{{ run.sh }}

## Observation

The output shows the usage of `setUserAuthenticationParameters` and `setUserAuthenticationValidityDurationSeconds` including the duration values.

{{ output.txt }}

## Evaluation

The test fails because the output shows:

- Line 279: `setUserAuthenticationValidityDurationSeconds(86400)` is called, configuring the key to remain unlocked for 86400 seconds (24 hours) after authentication.
- Line 281: `setUserAuthenticationParameters(86400, ...)` is also called with the same 24-hour duration.

For sensitive operations, keys should use `setUserAuthenticationParameters(0, type)` to require authentication for every cryptographic operation, ensuring that each use of the key requires biometric verification and user presence.
OWASP Mobile Application Security Testing Guide: output

                  
                  
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
                                              
    ../MASTG-DEMO-0090/MastgTest_reversed.java
    ❯❱ rules.mastg-android-biometric-no-confirmation-required
          [MASVS-AUTH-3] BiometricPrompt allows authentication without explicit user confirmation. For
          sensitive operations, consider using setConfirmationRequired(true).                         
                                                                                                      
           82┆ final BiometricPrompt prompt1 = new BiometricPrompt.Builder(this.context).setTitle("Test 1:
               No CryptoObject").setSubtitle("Insecure: No cryptographic binding").setDescription("Secret 
               returned directly without CryptoObject                                                     
               protection").setAllowedAuthenticators(32783).setConfirmationRequired(false).build();
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0092

---
platform: android
title: Uses of BiometricPrompt without Explicit User Confirmation with semgrep
id: MASTG-DEMO-0092
code: [kotlin]
test: MASTG-TEST-0329
---

## Sample

This sample demonstrates the use of [`setConfirmationRequired()`](https://developer.android.com/reference/android/hardware/biometrics/BiometricPrompt.Builder#setConfirmationRequired(boolean)). It shows both, insecure configurations that allow authentication without explicit user action and secure configurations that require explicit confirmation.

When `setConfirmationRequired(false)` is used, passive biometrics (like face recognition) can authenticate the user as soon as the device detects their biometric data, without requiring them to tap a confirmation button.

{{ ../MASTG-DEMO-0090/MastgTest.kt # ../MASTG-DEMO-0090/MastgTest_reversed.java }}

## Steps

Run @MASTG-TOOL-0110 rules against the sample code.

{{ ../../../../rules/mastg-android-biometric-no-confirmation-required.yml }}

{{ run.sh }}

## Observation

The output shows the uses of `setConfirmationRequired()`.

{{ output.txt }}

## Evaluation

The test fails because the output shows one reference to a biometric authentication that disables explicitly user confirmation:

- Line 82: `setConfirmationRequired(false)` is called, which allows the authentication to succeed implicitly without the user actively confirming the action.
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘
                           
    MastgTest_reversed.java
    ❯❱ rules.mastg-android-biometric-device-credential-fallback
          [MASVS-AUTH-3] BiometricPrompt allows fallback to device credentials. For sensitive operations,
          consider using BIOMETRIC_STRONG only.                                                          
                                                                                                         
           38┆ final BiometricPrompt prompt1 = new BiometricPrompt.Builder(this.context).setTitle("Test 1:
               Device Credential").setSubtitle("Using DEVICE_CREDENTIAL (Security:                        
               FAIL)").setDescription("This allows also PIN/pattern/password                              
               authentication").setAllowedAuthenticators(32783).setDeviceCredentialAllowed(true).build(); 
            ⋮┆----------------------------------------
           38┆ final BiometricPrompt prompt1 = new BiometricPrompt.Builder(this.context).setTitle("Test 1:
               Device Credential").setSubtitle("Using DEVICE_CREDENTIAL (Security:                        
               FAIL)").setDescription("This allows also PIN/pattern/password                              
               authentication").setAllowedAuthenticators(32783).setDeviceCredentialAllowed(true).build();
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0089

---
platform: android
title: Uses of BiometricPrompt with Device Credential Fallback with semgrep
id: MASTG-DEMO-0089
code: [kotlin]
test: MASTG-TEST-0326
---

## Sample

The following sample demonstrates the use of the built-in [`android.hardware.biometrics.BiometricPrompt`](https://developer.android.com/reference/android/hardware/biometrics/BiometricPrompt) framework API (available from API level 28+) with different authenticator configurations used in `BiometricPrompt.Builder()`.

It shows both weaker configurations that allow fallback to device credentials (PIN, pattern, password), which are more susceptible to compromise (e.g., through shoulder surfing) and secure configurations that requires a strong biometric authentication only.

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

Let's run @MASTG-TOOL-0110 rules against the sample code.

{{ ../../../../rules/mastg-android-biometric-device-credential-fallback.yml }}

{{ run.sh }}

## Observation

The output shows all usages of APIs that configure biometric authentication.

{{ output.txt }}

## Evaluation

The test fails because the output shows references to biometric authentication configurations that allow fallback to device credentials:

- Line 38: `setAllowedAuthenticators(32783)` is called with `BIOMETRIC_STRONG | DEVICE_CREDENTIAL`, which allows the user to authenticate with either biometrics or their device PIN/pattern/password. The value `32783` is the sum of `32768` and `15`. Decompiled code contains integer values of the [`Authenticator` constants](https://developer.android.com/reference/android/hardware/biometrics/BiometricManager.Authenticators) instead of the name:
    - `BIOMETRIC_STRONG` = 15 (0x000F)
    - `BIOMETRIC_WEAK` = 255 (0x00FF)
    - `DEVICE_CREDENTIAL` = 32768 (0x8000)
- Also in line 38: [`setDeviceCredentialAllowed(true)`](https://developer.android.com/reference/android/hardware/biometrics/BiometricPrompt.Builder#setDeviceCredentialAllowed(boolean)) is called and can give the user the option to authenticate with their device PIN, pattern, or password instead of a biometric.

For sensitive operations, the app should use [`BIOMETRIC_STRONG`](https://developer.android.com/identity/sign-in/biometric-auth#declare-supported-authentication-types) to enforce biometric-only authentication.
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘
                           
    MastgTest_reversed.java
    ❯❱ rules.mastg-android-data-unencrypted-shared-storage-no-user-interaction-mediastore
          [MASVS-STORAGE] Make sure to want this data to be shared with other apps
                                                                                  
            8┆ import android.provider.MediaStore;
            ⋮┆----------------------------------------
           35┆ Uri textUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0005

---
platform: android
title: App Writing to External Storage via the MediaStore API
id: MASTG-DEMO-0005
code: [kotlin]
test: MASTG-TEST-0202
---

## Sample

The snippet below shows sample code that uses the `MediaStore` API to write a file to shared storage in a path like `/storage/emulated/0/Download/` which does not require any permissions to access and is shared with other apps.

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

Let's run our @MASTG-TOOL-0110 rule against the sample code.

{{ ../../../../rules/mastg-android-data-unencrypted-shared-storage-no-user-interaction-apis.yml }}

{{ run.sh }}

## Observation

The rule has identified 2 locations that indicate a use of MediaStore API.

{{ output.txt }}

The first location is the import statement for the `MediaStore` API and the second location is where the `MediaStore` API is used to write to shared storage.

## Evaluation

After reviewing the decompiled code at the locations specified in the output (file and line number) we can conclude that the test fails because the file written by this instance contains sensitive data, specifically a API key.
OWASP Mobile Application Security Testing Guide: evaluation

Class: android.app.SharedPreferencesImpl$EditorImpl, Method: putString, Params: UnencryptedGitHubToken, [CREDENTIAL_REDACTED]
Class: javax.crypto.Cipher, Method: getInstance, Params: AES/GCM/NoPadding
Class: java.security.KeyStore, Method: getEntry, Params: mastgKey, void
Class: javax.crypto.Cipher, Method: init, Params: 1, <instance: java.security.Key, $className: android.security.keystore2.AndroidKeyStoreSecretKey>, <instance: java.security.SecureRandom>
Class: javax.crypto.Cipher, Method: init, Params: 1, <instance: java.security.Key, $className: android.security.keystore2.AndroidKeyStoreSecretKey>
Class: javax.crypto.Cipher, Method: doFinal, Params: [CREDENTIAL_REDACTED]
Class: android.util.Base64, Method: encodeToString, Params: 0x53e09f5c462870a214466544f752de9dab78e423147bbf8274f34f81c28e6474b3725fe8457be0cddc5b4330fc75ed6b..., 0
Class: android.app.SharedPreferencesImpl$EditorImpl, Method: putString, Params: EncryptedAwsKey, U+CfXEYocKIURmVE91Lenat45CMUe7+CdPNPgcKOZHSzcl/oRXvgzdxbQzD8de1r

Class: android.app.SharedPreferencesImpl$EditorImpl, Method: putStringSet, Params: UnencryptedPreSharedKeys, [CREDENTIAL_REDACTED]
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBALfX7kbfFv3pc3JjOHQ=
-----END PRIVATE KEY-----,[CREDENTIAL_REDACTED]
gJXS9EwpuzK8U1TOgfplwfKEVngCE2D5FNBQWvNmuHHbigmTCabsA=
-----END PRIVATE KEY-----
OWASP Mobile Application Security Testing Guide: output

Log.v("MASTG", "key: MAS-Sensitive-Value")
Log.i("MASTG", "key: MAS-Sensitive-Password")
Log.w("MASTG", "test: MAS-Sensitive-Value-IV")
Log.d("MASTG", "test: MAS-Sensitive-Value-IV-2")
Log.e("MASTG", "test: MAS-Sensitive-Value")
Log.wtf("MASTG", "test: MAS-Sensitive-Value")
Log.wtf(0, "MASTG", "test: MAS-Sensitive-Value", null, false, false)
Logger.severe("MAS-Sensitive-Key")
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0006

---
platform: android
title: Tracing Common Logging APIs Looking for Secrets
id: MASTG-DEMO-0006
code: [kotlin]
test: MASTG-TEST-0203
---

## Sample

The snippet contains many calls to logging APIs which are used to print out secrets such as passwords or IVs.

{{ MastgTest.kt }}

## Steps

Execute `frida-trace` against the sample app, tracing logging classes and methods.

{{ run.sh }}

## Observation

`frida-trace` has identified several instances where log output has been printed.

{{ output.txt }}

As a reference, this is the corresponding logcat output obtained from Android Studio.

{{ logcat_output.txt }}

## Evaluation

Review each of the reported instances by using keywords and known secrets (e.g. passwords or usernames or values you keyed into the app).

Note: You could refine the test to input a known secret and then search for it in the logs.
OWASP Mobile Application Security Testing Guide: logcat output

2024-05-14 10:30:06.864  6966-6966  MASTG                   org.owasp.mastestapp                 V  key: MAS-Sensitive-Value
2024-05-14 10:30:06.866  6966-6966  MASTG                   org.owasp.mastestapp                 I  key: MAS-Sensitive-Password
2024-05-14 10:30:06.867  6966-6966  MASTG                   org.owasp.mastestapp                 W  test: MAS-Sensitive-Value-IV
2024-05-14 10:30:06.867  6966-6966  MASTG                   org.owasp.mastestapp                 D  test: MAS-Sensitive-Value-IV-2
2024-05-14 10:30:06.867  6966-6966  MASTG                   org.owasp.mastestapp                 E  test: MAS-Sensitive-Value
2024-05-14 10:30:06.869  6966-6966  MASTG                   org.owasp.mastestapp                 E  test: MAS-Sensitive-Value
2024-05-14 10:30:06.881  6966-6966  myLogger                org.owasp.mastestapp                 E  MAS-Sensitive-Key
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0070

---
platform: android
title: Sensitive Data Stored Unencrypted via Room Database
id: MASTG-DEMO-0070
code: [kotlin]
test: MASTG-TEST-0306
status: placeholder
note: This placeholder reserves the ID for a demo illustrating the insecure storage of sensitive data using the Android Room Persistence Library without integrating an external encryption solution (like SQLCipher). It directly corresponds to the MASTG-TEST-0306.
---
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 3 Code Findings │
└─────────────────┘
                                          
    ../MASTG-DEMO-0020/AndroidManifest.xml
    ❯❱ rules.mastg-android-backup-manifest-allow-backup
          [MASVS-STORAGE-2] allowBackup detected as true.
                                                         
            6┆ android:allowBackup="true"
   
    ❯❱ rules.mastg-android-backup-manifest-backup-rules
          [MASVS-STORAGE-2] Backup rules detected.
                                                  
            7┆ android:dataExtractionRules="@xml/data_extraction_rules"
            ⋮┆----------------------------------------
            8┆ android:fullBackupContent="@xml/backup_rules"
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0034

---
platform: android
title: Backup and Restore App Data with semgrep
id: MASTG-DEMO-0034
code: [kotlin]
test: MASTG-TEST-0262
---

## Sample

This demo uses the sample from @MASTG-DEMO-0020.

{{ ../MASTG-DEMO-0020/MastgTest.kt # ../MASTG-DEMO-0020/AndroidManifest.xml # ../MASTG-DEMO-0020/backup_rules.xml }}

## Steps

1. Read the AndroidManifest.xml and backup_rules.xml files.
2. Run the semgrep script.

{{ run.sh # ../../../../rules/mastg-android-backup-manifest.yml }}

## Observation

The output contains all backup-related attributes from the AndroidManifest.xml file.

{{ output.txt }}

## Evaluation

The test fails because the sensitive file `secret.txt` ends up in the backup. This is due to:

- The `android:allowBackup="true"` attribute in the AndroidManifest.xml file.
- The `android:fullBackupContent="@xml/backup_rules"` attribute is present in the AndroidManifest.xml file.
- The `backup_rules.xml` file is present in the APK and does not exclude **all** sensitive files.

{{ ../MASTG-DEMO-0020/backup_rules.xml }}

The backup includes all files in the app's data directory except for `backup_excluded_secret.txt`.
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0010

---
platform: android
title: File System Snapshots from Internal Storage
id: MASTG-DEMO-0010
code: [kotlin]
test: MASTG-TEST-0207
---

## Sample

The snippet below shows sample code that creates a file on the **internal storage** using using the [`filesDir`](https://developer.android.com/reference/android/content/Context#getFilesDir()) property of the context object.

{{ MastgTest.kt }}

## Steps

1. Install an app on your device.
2. Execute `run_before.sh` which runs @MASTG-TOOL-0004.
3. Open an app and exercise it to trigger file creations.
4. Execute `run_after.sh`.
5. Close the app once you finish testing.

{{ run_before.sh # run_after.sh }}

## Observation

There is a list of all created files inside `output.txt`.

{{ output.txt }}

Their content is inside the `./new_files/` directory and contains:

A password:

{{ new_files/secret.txt }}

The file was created in `/data/user/0/org.owasp.mastestapp/files/` which is equivalent to `/data/data/org.owasp.mastestapp/files/`.

## Evaluation

This test fails because the file is not encrypted and contains sensitive data (a password). You can further confirm this by reverse engineering the app and inspecting the code.
OWASP Mobile Application Security Testing Guide: output

                  
                  
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
                           
    MastgTest_reversed.java
    ❯❱ rules.mastg-android-data-unencrypted-shared-storage-no-user-interaction-external-api-scoped
          [MASVS-STORAGE] These locations might be accessible to other apps on Android 10 and below given
          relevant permissions                                                                           
                                                                                                         
           25┆ File externalStorageDir = this.context.getExternalFilesDir(null);
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0004

---
platform: android
title: App Writing to External Storage with Scoped Storage Restrictions
id: MASTG-DEMO-0004
code: [kotlin]
test: MASTG-TEST-0202
---

## Sample

The snippet below shows sample code that creates a file in external storage using the `getExternalFilesDir` API which returns a path to the app's external files directory (e.g. `/storage/emulated/0/Android/data/org.owasp.mastestapp/files`) and does not require any permissions to access. Scoped storage applies since the app targets Android 12 (API level 31) which is higher than Android 10 (API level 29).

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

Let's run our @MASTG-TOOL-0110 rule against the reversed java code.

{{ ../../../../rules/mastg-android-data-unencrypted-shared-storage-no-user-interaction-apis.yml }}

{{ run.sh }}

## Observation

The rule has identified one location in the code file where an API, `getExternalFilesDir`, is used to write to external storage with scoped storage restrictions.

{{ output.txt }}

## Evaluation

After reviewing the decompiled code at the location specified in the output (file and line number) we can conclude that the test fails because the file written by this instance contains sensitive data, specifically a password.
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0069

---
platform: android
title: Sensitive Data Stored Unencrypted via DataStore
id: MASTG-DEMO-0069
code: [kotlin]
test: MASTG-TEST-0305
status: placeholder
note: This placeholder reserves the ID for a demo illustrating the insecure storage of sensitive data using the modern Jetpack DataStore API without implementing secure encryption mechanisms. It directly corresponds to the MASTG-TEST-0305.
---
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0020

---
platform: android
title: Data Exclusion using backup_rules.xml with Backup Manager
id: MASTG-DEMO-0020
code: [kotlin]
test: MASTG-TEST-0216
---

## Sample

The following samples contain:

- the Kotlin code that creates two files inside [`filesDir`](https://developer.android.com/reference/android/content/Context#getFilesDir()).
- the AndroidManifest.xml with the `android:fullBackupContent` attribute (for Android 11 and lower).
- the `backup_rules.xml` file including a rule to exclude one of the files using an `<exclude>` element.

{{ MastgTest.kt # AndroidManifest.xml # backup_rules.xml }}

## Steps

1. Install the target app on your device.
2. Open the app and exercise it to trigger file creations.
3. Execute `run.sh`.

{{ run.sh # ../../../../utils/mastg-android-backup-bmgr.sh }}

For simplicity, in `run.sh` we restrict the files to the `filesDir` directory (`/data/user/0/org.owasp.mastestapp/files/` which is equivalent to `/data/data/org.owasp.mastestapp/files/`).

The `run.sh` script does the following:

1. Takes a snapshot of the app data before the backup.
2. Runs the backup script, which:
    - backs up the app data.
    - uninstalls the app.
    - restores the app data.
3. Takes a snapshot of the app data after the restore.
4. Retrieves the list of restored files from the device.

## Observation

The output contains:

- `output.txt`: the output of the `run.sh` script.
- `output_before.txt`: the list of files before the backup.
- `output_after.txt`: the list of files after the restore.
- `restored_files/`: the directory containing the restored files.

{{ output.txt # output_before.txt # output_after.txt }}

## Evaluation

The test fails because `secret.txt` is restored from the backup and it contains sensitive data.

{{ restored_files/secret.txt }}

Note that `output_after.txt` does not contain the `backup_excluded_secret.txt` file, which is expected as it was marked as `exclude` in the `backup_rules.xml` file.
OWASP Mobile Application Security Testing Guide: output

adbd is already running as root
Backup Manager now enabled
Package org.owasp.mastestapp with result: Success
/data/app/~~Es7NACiEKrtQIzZpqtLPzw==/org.owasp.mastestapp-GvkjkmAqRCTmzufVHw8YNg==/base.apk: 1 file pulled, 0 skipped. 165.5 MB/s (25924184 bytes in 0.149s)
Success
Success
Selected transport com.google.android.gms/.backup.BackupTransportService (formerly com.android.localtransport/.LocalTransport)
Done
/data/user/0/org.owasp.mastestapp/files/profileInstalled: 1 file pulled, 0 skipped. 0.0 MB/s (24 bytes in 0.001s)
/data/user/0/org.owasp.mastestapp/files/secret.txt: 1 file pulled, 0 skipped. 0.0 MB/s (15 bytes in 0.001s)
OWASP Mobile Application Security Testing Guide: output before

/data/user/0/org.owasp.mastestapp/files/secret.txt
/data/user/0/org.owasp.mastestapp/files/backup_excluded_secret.txt
/data/user/0/org.owasp.mastestapp/files/profileInstalled