-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Port MASTG v1->v2 MASTG-TEST-0002: Testing Local Storage for Input Validation (android) (by @appknox) #3328
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
Co-authored-by: pruDhv! <[email protected]>
|
@cpholguera, upon adding the depreciation note, getting branch gets a conflict |
|
Maybe the branch was a bit old. We added "profiles" now for all tests. I fixed the conflict for you Please add |
|
The new profiles (previously known as "levels") are defined here: https://docs.google.com/document/d/1paz7dxKXHzAC9MN7Mnln1JiZwBNyg7Gs364AJ6KudEs/edit?usp=sharing |
Done |
|
@cpholguera please review it |
|
Please fix the issues reported by Copilot in section "Comments suppressed due to low confidence (5)" Also, I agree with Copilot's comment about:
If you're conducting a pentest, would you report this as an issue? "The app uses |
|
There's another problem that will probably be solved when you fix the copilot issues. Are you able to read these logs? https://github.com/OWASP/owasp-mastg/actions/runs/15554645412/job/43792346017?pr=3328
|
|
@cpholguera please check |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR ports MASTG-TEST-0002 from version 1 to version 2, creating a new test for detecting use of local storage for input validation in Android applications. The focus shifts from general local storage testing to specifically checking for integrity validation when reading from SharedPreferences.
- Deprecates the old MASTG-TEST-0002 and creates MASTG-TEST-0288 as the new version
- Implements static analysis detection for SharedPreferences usage without integrity checks
- Provides demonstration code showing both vulnerable and secure patterns using HMAC validation
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| tests/android/MASVS-CODE/MASTG-TEST-0002.md | Marks the original test as deprecated with reference to new version |
| tests-beta/android/MASVS-CODE/MASTG-TEST-0288.md | New test specification for detecting SharedPreferences without integrity validation |
| rules/mastg-android-local-storage-input-validation.yml | Semgrep rule to detect insecure SharedPreferences usage patterns |
| demos/android/MASVS-CODE/MASTG-DEMO-0061/ | Complete demonstration including vulnerable Java code, secure Kotlin implementation, and analysis output |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| - L2 | ||
| profiles: [L1, L2] | ||
| status: deprecated | ||
| covered_by: [MASTG-TEST-0281] |
Copilot
AI
Aug 31, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deprecation references MASTG-TEST-0281, but the actual replacement test created in this PR is MASTG-TEST-0288. This should be corrected to reference the correct test ID.
| covered_by: [MASTG-TEST-0281] | |
| covered_by: [MASTG-TEST-0288] |
|
|
||
| ## Steps | ||
|
|
||
| 1. Run a static analysis tool such as @MASTG-TOOL-0110 on the code and look for uses of the `putString` and `getString`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an old file
|
|
||
| ### Evaluation | ||
|
|
||
| The test fails as the code does not use an `HMAC` integrity check together with `SharedPreferences` data. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please describe how, because of this, an attacker can exploit the app. Use references to techniques when possible.
|
@cpholguera requested changes be made. Could you please check |
|
@cpholguera can you please review |
|
@cpholguera can you please review it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @jeel38 ! Really nice pen-test example ^^ Left some suggestions to improve this test. Feel free to reach out if something is unclear
| --- | ||
| platform: android | ||
| title: Local Storage for Input Validation with semgrep | ||
| id: MASTG-DEMO-0061 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might need a new id just before merge (demo 61 exists)
| --- | ||
| title: Use of Local Storage for Input Validation | ||
| platform: android | ||
| id: MASTG-TEST-0288 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might need a new id just before merge (test 288 already exists)
|
|
||
| ## Overview | ||
|
|
||
| Data stored in Android's `SharedPreference`s can be tampered with on a rooted device. If an application reads this data without verifying its integrity (e.g., with an HMAC signature), it can lead to security vulnerabilities. This test checks if the application properly validates data read from local storage. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already really well-written @jeel38! How about we generalise it a bit and add a note, comment, or intro that this test is not only about SharedPrefs, but also any other local storage, like the v1 test mentions?
Additionally, we should add the requirement for data authenticity (HMAC is about both integrity and authenticity after all):
| Data stored in Android's `SharedPreference`s can be tampered with on a rooted device. If an application reads this data without verifying its integrity (e.g., with an HMAC signature), it can lead to security vulnerabilities. This test checks if the application properly validates data read from local storage. | |
| Data stored in Android's `SharedPreference`s can be tampered with on a rooted device. If an application reads this data without verifying its integrity and authenticity (e.g., with an HMAC signature), it can lead to security vulnerabilities. This test checks if the application properly validates data read from local storage. |
What we could highlight here to help the reader is that SHA (integrity check without authenticity check) might not be optimal unless the SHA hashes are stored in a backend server. Therefore, by using HMAC, we only need to store the key safely and the data + HMAC hash in the local storage.
|
|
||
| ## Evaluation | ||
|
|
||
| The test fails as the application does not verify the integrity of data loaded from `SharedPreferences`. Without an integrity check like `HMAC`, an attacker with root access can directly edit the SharedPreferences XML file, modifying values to grant themselves higher privileges. The app then reads and acts on this tampered data, leading to a critical security failure, like privilege escalation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| The test fails as the application does not verify the integrity of data loaded from `SharedPreferences`. Without an integrity check like `HMAC`, an attacker with root access can directly edit the SharedPreferences XML file, modifying values to grant themselves higher privileges. The app then reads and acts on this tampered data, leading to a critical security failure, like privilege escalation. | |
| The test fails if the application does not verify the integrity and authenticity of data loaded from local storage such as `SharedPreferences`. |
I would consolidate the other sentences as part of the overview to explain the risk etc...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please Refer to this comment: #3328 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To my understanding, @cpholguera pointed out that suggestion for the DEMO, this is the TEST file.
Reading this TEST's Overview and Evaluation sections seems to be some repetition.
| @@ -0,0 +1,24 @@ | |||
| --- | |||
| title: Use of Local Storage for Input Validation | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about the following? Input validation to me sounds validating input rather than checking the integrity/authenticity of data.
| title: Use of Local Storage for Input Validation | |
| title: Validation of Local Storage Data |
or
| title: Use of Local Storage for Input Validation | |
| title: Integrity and Authenticity Validation of Local Storage Data |
| @@ -0,0 +1 @@ | |||
| NO_COLOR=true semgrep -c ../../../../rules/mastg-android-local-storage-input-validation.yml ./MastgTest_reversed.java --text -o output.txt No newline at end of file | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| NO_COLOR=true semgrep -c ../../../../rules/mastg-android-local-storage-input-validation.yml ./MastgTest_reversed.java --text -o output.txt | |
| NO_COLOR=true semgrep -c ../../../../rules/mastg-android-local-storage-input-validation.yml ./MastgTest_reversed.java > output.txt |
to align with rest of project
| SecureSharedPreferences insecurePrefs = new SecureSharedPreferences(this.context, false); | ||
| insecurePrefs.saveData("user_role_insecure", "user"); | ||
| SecureSharedPreferences securePrefs = new SecureSharedPreferences(this.context, true); | ||
| securePrefs.saveData("user_role_secure", "user"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracting this file gives quite a different result. Most importantly, the following. Therefore, Semgrep finds no results for me.
| SecureSharedPreferences insecurePrefs = new SecureSharedPreferences(this.context, false); | |
| insecurePrefs.saveData("user_role_insecure", "user"); | |
| SecureSharedPreferences securePrefs = new SecureSharedPreferences(this.context, true); | |
| securePrefs.saveData("user_role_secure", "user"); | |
| saveData("user_role_insecure", "user", false); | |
| saveData("user_role_secure", "user", true); |
| return "INITIAL SETUP COMPLETE.\n\n" + | ||
| "The role for both secure and insecure tests has been set to 'user'.\n\n" + | ||
| "ACTION REQUIRED:\n" + | ||
| "1. Use a file explorer or ADB shell on a rooted device.\n" + | ||
| "2. Go to: /data/data/org.owasp.mastestapp/shared_prefs/\n" + | ||
| "3. Open the file: app_settings.xml\n" + | ||
| "4. Change BOTH <string>user</string> values to <string>admin</string>.\n" + | ||
| "5. Save the file and run this test again to see the results." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done on he pen-testing example! 👏 I followed the steps but sadly could not "tamper" it.
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="user_role_secure_hmac">690d026aeeba673e7225ee95a3460a0054752777afec8e4fb7ec8294934011ed</string>
<boolean name="setup_complete" value="true" />
<string name="user_role_insecure">admin</string>
<string name="user_role_secure">admin</string>
</map> is the file state between the 2 steps
| results.append(">> OUTCOME: NOT TAMPERED. The role is still '$secureRole', and its HMAC signature is valid.\n") | ||
| } | ||
|
|
||
| results.append("\n\nTest complete. To run the setup again, please clear the application's data in Android Settings and restart the test.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fyi restarting the application (thus test) would rewrite the xml. No need for clearing app data
Closes #2995
This PR ports MASTG-TEST-0002 from version 1 to version 2, creating a new test for detecting use of local storage for input validation in Android applications. The focus shifts from general local storage testing to specifically checking for integrity validation when reading from
SharedPreferences.SharedPreferencesusage without integrity checksSharedPreferenceswithout integrity validationSharedPreferencesusage patterns