Skip to content

Port MASTG v1->v2 MASTG-TEST-0002: Testing Local Storage for Input Validation (android) (by @appknox)#3328

Open
jeel38 wants to merge 23 commits intoOWASP:masterfrom
jeel38:MASTG-TEST-0002_draft
Open

Port MASTG v1->v2 MASTG-TEST-0002: Testing Local Storage for Input Validation (android) (by @appknox)#3328
jeel38 wants to merge 23 commits intoOWASP:masterfrom
jeel38:MASTG-TEST-0002_draft

Conversation

@jeel38
Copy link
Collaborator

@jeel38 jeel38 commented Jun 10, 2025

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.

  • 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
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 code, and analysis output

@jeel38
Copy link
Collaborator Author

jeel38 commented Jun 10, 2025

@cpholguera, upon adding the depreciation note, getting branch gets a conflict

@cpholguera
Copy link
Collaborator

Maybe the branch was a bit old. We added "profiles" now for all tests. I fixed the conflict for you

Please add profiles to tests-beta/android/MASVS-CODE/MASTG-TEST-0281.md as well

@cpholguera
Copy link
Collaborator

The new profiles (previously known as "levels") are defined here: https://docs.google.com/document/d/1paz7dxKXHzAC9MN7Mnln1JiZwBNyg7Gs364AJ6KudEs/edit?usp=sharing

@cpholguera cpholguera requested a review from Copilot June 10, 2025 08:36

This comment was marked as outdated.

@jeel38
Copy link
Collaborator Author

jeel38 commented Jun 10, 2025

Maybe the branch was a bit old. We added "profiles" now for all tests. I fixed the conflict for you

Please add profiles to tests-beta/android/MASVS-CODE/MASTG-TEST-0281.md as well

Done

@jeel38
Copy link
Collaborator Author

jeel38 commented Jun 10, 2025

@cpholguera please review it

@cpholguera
Copy link
Collaborator

Please fix the issues reported by Copilot in section "Comments suppressed due to low confidence (5)"


Also, I agree with Copilot's comment about:

"The output file shows usages of the input validation using putString and getString in the code."

The phrasing is misleading: this test detects storage/retrieval calls, not input validation.

If you're conducting a pentest, would you report this as an issue? "The app uses putString() and getString()." The same goes for an automated security testing tool, would you like it to report this? Wouldn't that be noisy / lots of false positives?

@cpholguera
Copy link
Collaborator

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

ERROR - Error reading page 'MASTG/demos/android/MASVS-CODE/MASTG-DEMO-0054/MASTG-DEMO-0054.md': Snippet at path '../../../../rules/mastg-android-local-storage-for-input-validation.yml' could not be found

@jeel38
Copy link
Collaborator Author

jeel38 commented Aug 11, 2025

@cpholguera please check

Copy link
Contributor

Copilot AI left a 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]
Copy link

Copilot AI Aug 31, 2025

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.

Suggested change
covered_by: [MASTG-TEST-0281]
covered_by: [MASTG-TEST-0288]

Copilot uses AI. Check for mistakes.

## Steps

1. Run a static analysis tool such as @MASTG-TOOL-0110 on the code and look for uses of the `putString` and `getString`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

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

@jeel38
Copy link
Collaborator Author

jeel38 commented Sep 17, 2025

@cpholguera requested changes be made. Could you please check

@jeel38
Copy link
Collaborator Author

jeel38 commented Oct 7, 2025

@cpholguera can you please review

@jeel38
Copy link
Collaborator Author

jeel38 commented Oct 27, 2025

@cpholguera can you please review it

@cpholguera cpholguera requested review from Diolor and Copilot October 27, 2025 12:00
Copy link
Contributor

Copilot AI left a 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.

Copy link
Collaborator

@Diolor Diolor left a 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

---
title: Use of Local Storage for Input Validation
platform: android
id: MASTG-TEST-0288
Copy link
Collaborator

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)

@@ -0,0 +1,24 @@
---
title: Use of Local Storage for Input Validation
Copy link
Collaborator

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.

Suggested change
title: Use of Local Storage for Input Validation
title: Validation of Local Storage Data

or

Suggested change
title: Use of Local Storage for Input Validation
title: Integrity and Authenticity Validation of Local Storage Data

Comment on lines +23 to +26
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");
Copy link
Collaborator

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.

Suggested change
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);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share your output.txt as showing the result of finding

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file LLM generated or did you actually pull it from the device? Please use the MastgTest.kt as input on the demo app.

The output.txt of the actual MastgTest.kt which is very different than this file is empty.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a LLM Generated, it's a Reversed while MastgTest_reversed.java from MastgTest.kt file

Comment on lines +51 to +58
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."
Copy link
Collaborator

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to edit "user_role_insecure" value and restart the application

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did change both values as explained in step 5.
Both scenarios 1 and 2 display NOT EXPLOITED and NOT TAMPERED, respectively.

Image Image

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tested on physical rooted Android device. Please refer to the attached POC video

Screen.Recording.2026-01-30.at.12.mp4

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.")
Copy link
Collaborator

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To get tamper data, you have to restart the application, clearing app data is reset to application default settings.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message/user direction is wrong.

  1. If I restart the application it will override the shared prefs to default -> "user"
  2. Thus clearing the data is not required.
Image

In combination with the fact that I could not "tamper" the app as explained in the other comment, please carefully re-check the demo and its instructions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refer the POC: #3328 (comment)

@jeel38 jeel38 requested a review from Diolor December 12, 2025 08:30
@jeel38
Copy link
Collaborator Author

jeel38 commented Dec 12, 2025

@Diolor please review, changes are completed

@jeel38
Copy link
Collaborator Author

jeel38 commented Jan 7, 2026

@Diolor please review

Copy link
Collaborator

@Diolor Diolor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @jeel38, please carefully check the comments.
There are also unaddressed comments from my previous review. Please address those too before requesting a new review.

- L2
profiles: [L1, L2]
status: deprecated
covered_by: [MASTG-TEST-0288]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indicating that this might change

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is been addressed

Comment on lines 19 to 21
For any publicly accessible data storage, any process can override the data. This means that input validation needs to be applied the moment the data is read back again.

> Note: The same is true for private accessible data on a rooted device
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This v1 test addresses 2 issues:

  1. Publicly accessible data
  2. Private accessible data on a rooted device

As stated in the comment on the Tests' overview, the second case is not addressed on the v2 test.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the demo covers "Private accessible data on a rooted device" as per the static analysis of the previous V1 test. Private test data path: /data/data/org.owasp.mastestapp/shared_prefs


## Evaluation

The test fails if the application does not verify the integrity and authenticity of data loaded from local storage such as `SharedPreferences`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean we should verify integrity + authenticity for all data in SharedPrefs? E.g. a true/false boolean if the app should render light or dark them is not important.

Without adding the context of sensitive data or data that could harm the apps, this wording is very generalised.

package org.owasp.mastestapp

import android.content.Context
import android.content.SharedPreferences
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is been addressed

Comment on lines +51 to +58
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."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did change both values as explained in step 5.
Both scenarios 1 and 2 display NOT EXPLOITED and NOT TAMPERED, respectively.

Image Image

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.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message/user direction is wrong.

  1. If I restart the application it will override the shared prefs to default -> "user"
  2. Thus clearing the data is not required.
Image

In combination with the fact that I could not "tamper" the app as explained in the other comment, please carefully re-check the demo and its instructions.

Comment on lines +23 to +26
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");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this file LLM generated or did you actually pull it from the device? Please use the MastgTest.kt as input on the demo app.

The output.txt of the actual MastgTest.kt which is very different than this file is empty.

Comment on lines +14 to +15
23┆ SecureSharedPreferences insecurePrefs = new
SecureSharedPreferences(this.context, false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: You might have hard wrapping in your editor.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is been addressed

@jeel38
Copy link
Collaborator Author

jeel38 commented Jan 30, 2026

@Diolor please review it

@serek8 serek8 self-requested a review January 30, 2026 11:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MASTG v1->v2 MASTG-TEST-0002: Testing Local Storage for Input Validation (android)

4 participants