-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Update test and add new demos for screenshot prevention in Android #3457
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
Open
cpholguera
wants to merge
31
commits into
master
Choose a base branch
from
more-android-screenshots-testing
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 29 commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
bb3bb4d
Enhance documentation on screenshot handling in Android, detailing sy…
cpholguera fff4ec9
Revise guidelines on preventing sensitive data capture, detailing ris…
cpholguera a9e5cbc
Add additional rules for FLAG_SECURE handling and recents screenshot …
cpholguera 870fca7
Add guidelines for identifying sensitive screens during testing
cpholguera 875244f
Update FLAG_SECURE usage examples and documentation in Android MASTG-…
cpholguera 1a66957
Add new MASTG-DEMO-0062 for setRecentsScreenshotEnabled in Android 14+
cpholguera 6604db3
Add new MASTG-DEMO-0063 for Jetpack Compose Dialogs
cpholguera fa08647
Remove redundant rules for recents screenshot enabled/disabled in sen…
cpholguera 771a7fc
Enhance documentation for screen capture prevention APIs, including d…
cpholguera 81c6310
rm extra ref to file
cpholguera c58f7b3
Merge branch 'master' of https://github.com/OWASP/owasp-mastg into mo…
cpholguera 7af35bd
refine documentation on FLAG_SECURE usage for Android UI components
cpholguera a6bbca3
refine wording and clarity in MASTG-TEST-0291.md regarding FLAG_SECUR…
cpholguera e4d8754
fix regex
cpholguera 1c3369a
Split best practices for preventing screenshots in Android apps.
cpholguera 4a483b4
Split tests for preventing screenshots in Android apps.
cpholguera 3250c83
Fix test refs
cpholguera de7c3a0
add refs
cpholguera 3111eda
link best to knowledge
cpholguera 3c6eb43
Clarify wording in MASTG-TEST-0291.md for better readability
cpholguera 13975cb
Add best practice for non-caching input types in sensitive fields
cpholguera 1d946d8
Update MASTG-BEST-0018.md to clarify usage of SecureFlagPolicy.Secure…
cpholguera 01e9d69
Add reference to overlay attack warnings and improve wording in MASTG…
cpholguera 83c1346
Correct MASTG-KNOW-0053 location
cpholguera 8d83288
Update MASTG-KNOW-0022.md to correct Tapjacking reference and add bes…
cpholguera 532d4a1
Update best practices and knowledge documents for screenshot preventi…
cpholguera 07a89e6
Add MASTG-KNOW-0107.md for screenshots and screen recording detection…
cpholguera 5c8a99e
fix indentation
cpholguera d9ff8d4
Merge branch 'master' into more-android-screenshots-testing
cpholguera a95e414
Apply suggestions from code review
cpholguera b18f69c
Merge branch 'master' of https://github.com/OWASP/owasp-mastg into mo…
cpholguera File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
--- | ||
title: Use `setRecentsScreenshotEnabled` to Prevent Screenshots When Backgrounded | ||
alias: preventing-screenshots-when-backgrounded | ||
id: MASTG-BEST-0015 | ||
parent: MASTG-BEST-0014 | ||
knowledge: [MASTG-KNOW-0053] | ||
platform: android | ||
component: android.app.Activity | ||
available_since: 33 | ||
--- | ||
|
||
Preventing screenshots when an app is backgrounded helps protect sensitive data from being exposed in system-generated snapshots used by the [Recents screen](https://developer.android.com/guide/components/activities/recents). This is especially important for apps that handle sensitive information, such as banking, healthcare, or enterprise apps. For example, a banking app should ensure that account balances, transaction details, or card numbers never appear in the Recents screen, unless the user explicitly chooses to allow it using an in-app setting. | ||
|
||
Even though **system-generated snapshots** are sandboxed, they may still be accessible on rooted or compromised devices or through forensic acquisition. | ||
|
||
Using `FLAG_SECURE` consistently on all UI components as indicated in @MASTG-BEST-0014 helps prevent system-generated snapshots from showing sensitive data in the [Recents screen](https://developer.android.com/guide/components/activities/recents) when the app is backgrounded. However, getting it right can be challenging, as there's no global setting to enforce it across the entire app. | ||
|
||
Starting with Android 13 (API level 33), you can use [`setRecentsScreenshotEnabled(false)`](https://developer.android.com/reference/android/app/Activity#setRecentsScreenshotEnabled(boolean)) to ensure that the app's content is not shown in the Recents screen when backgrounded. | ||
|
||
- The snapshots saved to `/data/system_ce/<user_id>/snapshots` will be blank/obscured. | ||
- The previews in the Recents screen will be blank after the user switches away from the app completely, similar to the behavior of `FLAG_SECURE`. | ||
|
||
!!! warning "What `setRecentsScreenshotEnabled` Does Not" | ||
|
||
Setting `setRecentsScreenshotEnabled(false)` does not prevent user-initiated screenshots or screen recordings. | ||
|
||
- Users can take screenshots using the hardware shortcut and the content will appear in those screenshots. | ||
- Tapping "Screenshot" in the Recents screen will not work (the system may show a policy message depending on device/ROM). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
title: Use `SECURE_FLAG` to Prevent Screenshots and Screen Recording | ||
alias: use-secure-flag-to-prevent-screenshots-and-screen-recording | ||
id: MASTG-BEST-0016 | ||
parent: MASTG-BEST-0014 | ||
knowledge: [MASTG-KNOW-0053, MASTG-KNOW-0105, MASTG-KNOW-0106] | ||
platform: android | ||
component: android.view.Window | ||
available_since: 1 | ||
refs: | ||
- https://developer.android.com/security/fraud-prevention/activities#flag_secure | ||
- https://support.google.com/googleplay/android-developer/answer/16273414 | ||
- https://support.google.com/googleplay/android-developer/answer/14638385 | ||
- https://proandroiddev.com/multitasking-intrusion-and-preventing-screenshots-in-android-app-15bd8757c24d | ||
--- | ||
|
||
Setting [`FLAG_SECURE`](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_SECURE) on a window prevents screenshots (or makes them appear black), blocks screen recording, and hides content on non-secure displays and ensures that the app's content is not shown in the [Recents screen](https://developer.android.com/guide/components/activities/recents) when backgrounded. | ||
|
||
<div style="display:flex; flex-wrap:wrap; gap:16px; align-items:flex-start; margin:16px 0;"> | ||
<figure style="flex:1 1 220px; margin:0; text-align:center;"> | ||
<img src="Images/Chapters/0x05d/task-switcher-without-flag-secure.png" width="200" alt="Task switcher without FLAG_SECURE"> | ||
<figcaption>Without <code>FLAG_SECURE</code></figcaption> | ||
</figure> | ||
<figure style="flex:1 1 220px; margin:0; text-align:center;"> | ||
<img src="Images/Chapters/0x05d/task-switcher-with-flag-secure.png" width="200" alt="Task switcher with FLAG_SECURE"> | ||
<figcaption>With <code>FLAG_SECURE</code></figcaption> | ||
</figure> | ||
</div> | ||
|
||
The flag is applied with [`addFlags()`](https://developer.android.com/reference/android/view/Window#addFlags(int)) or [`setFlags()`](https://developer.android.com/reference/android/view/Window#setFlags(int,int)). Common best practices include: | ||
|
||
- This flag cannot be applied globally. Apply the flag to all windows that can show sensitive data, including `Activity`, `Dialog`, `DialogFragment`, `AlertDialog`, or any custom window added via `WindowManager`. Sometimes apps **use a base UI class and use inheritance** to ensure all sensitive screens have it set. | ||
- Set the flag as early as possible in the lifecycle, before sensitive content is rendered. For example, setting it in `onCreate()` is better than `onResume()`, and trying to add the flag in `onPause()` is not effective, as the preview is created before this method is called. | ||
- Be careful with fragments and their lifecycle, as they can be added or removed dynamically. | ||
- Avoid clearing the flag during transitions (e.g., using [`clearFlags()`](https://developer.android.com/reference/android/view/Window#clearFlags(int)) or `setFlags()` without reapplying), as sensitive previews for the Recents screen can be captured before callbacks like `onPause()`. | ||
|
||
Note that you cannot set `FLAG_SECURE` directly on components that do not expose `getWindow()`, such as `android.widget.PopupWindow` or `android.widget.Toast`. | ||
- `android.view.View` and subclasses like `android.widget.TextView`, `android.widget.EditText`, `android.webkit.WebView`, `android.view.TextureView`, etc. don't support `FLAG_SECURE`. You must secure their containing Window instead. Alternatively, you can mask passwords and other sensitive by following the recommendations in @MASTG-BEST-0019. | ||
Check failure on line 38 in best-practices/MASTG-BEST-0016.md
|
||
|
||
For more information, refer to the official documentation. | ||
|
||
**Important:** Google warns that this approach isn't reliable for protecting against overlay attacks (@MASTG-KNOW-0022). See ["Secure sensitive activities - Best practices"](https://developer.android.com/security/fraud-prevention/activities#best-practices). | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
title: Use `setSecure` to Prevent Screenshots in SurfaceViews | ||
alias: preventing-screenshots-and-screen-recording | ||
id: MASTG-BEST-0017 | ||
parent: MASTG-BEST-0014 | ||
knowledge: [MASTG-KNOW-0053, MASTG-KNOW-0105, MASTG-KNOW-0106] | ||
platform: android | ||
component: android.view.SurfaceView | ||
available_since: 17 | ||
--- | ||
|
||
`SurfaceView` creates a separate surface that is not protected by `FLAG_SECURE` even if the containing window has it set. To protect content in a `SurfaceView`, use [`setSecure(true)`](https://developer.android.com/reference/android/view/SurfaceView#setSecure(boolean)) before the surface view's containing window is attached to the window manager. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
title: Use `SecureFlagPolicy.SecureOn` to Prevent Screenshots in Compose Components | ||
alias: use-secureon-in-compose-components | ||
id: MASTG-BEST-0018 | ||
parent: MASTG-BEST-0014 | ||
knowledge: [MASTG-KNOW-0053, MASTG-KNOW-0105, MASTG-KNOW-0106] | ||
platform: android | ||
component: androidx.compose.ui:ui | ||
available_since: 1.0.0 | ||
--- | ||
|
||
Use [`SecureFlagPolicy.SecureOn`](https://developer.android.com/reference/kotlin/androidx/compose/ui/window/SecureFlagPolicy#SecureOn) for Jetpack Compose dialogs and popups that display sensitive information (via [`DialogProperties.securePolicy`](https://developer.android.com/reference/kotlin/androidx/compose/ui/window/DialogProperties#securePolicy()) or [`PopupProperties.securePolicy`](https://developer.android.com/reference/kotlin/androidx/compose/ui/window/PopupProperties#securePolicy()) respectively). This applies the underlying Window's [`FLAG_SECURE`](https://developer.android.com/reference/android/view/WindowManager.LayoutParams#FLAG_SECURE), which blocks screenshots, screen recordings, display on insecure devices and prevents previews in the Recents screen. | ||
|
||
Define the policy at creation time and avoid toggling it while visible. If the dialog or popup should follow the host window's state, use [`SecureFlagPolicy.Inherit`](https://developer.android.com/reference/kotlin/androidx/compose/ui/window/SecureFlagPolicy#Inherit). Avoid [`SecureFlagPolicy.SecureOff`](https://developer.android.com/reference/kotlin/androidx/compose/ui/window/SecureFlagPolicy#SecureOff) for sensitive content. | ||
|
||
Be aware that the use of this API may interfere with workflows like screenshots or screen sharing. If your threat model allows, consider offering an explicit user option to disable secure mode for non-sensitive scenarios, but default to secure behavior. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
--- | ||
title: Use Non-Caching Input Types for Sensitive Fields | ||
alias: use-non-caching-input-types | ||
id: MASTG-BEST-0019 | ||
knowledge: [MASTG-KNOW-0055] | ||
platform: android | ||
refs: | ||
- https://developer.android.com/reference/android/text/InputType | ||
- https://developer.android.com/reference/kotlin/androidx/compose/foundation/text/KeyboardOptions | ||
--- | ||
|
||
Use non-caching input types for any UI element that handles sensitive information (passwords, passphrases, PINs, recovery phrases, payment data). Password-style input types instruct the on-screen keyboard not to cache or learn from the entered text and disable suggestions and auto-correction. Password variations disable dictionary learning and suggestions in most IMEs and prevent caching of entered secrets. | ||
|
||
Combine this practice with broader data leakage controls e.g., @MASTG-BEST-0014 when appropriate. | ||
|
||
Recommendations: | ||
|
||
- XML layouts (EditText) | ||
- Passwords: `android:inputType="textPassword"` | ||
- Numeric PINs: `android:inputType="numberPassword"` | ||
- Avoid: `textVisiblePassword` and plain `text`/`number` without password variation. | ||
|
||
- Programmatic (View-based UI) | ||
- Passwords: `setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD)` | ||
- Numeric PINs: `setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD)` | ||
- Optionally disable suggestions for non-password sensitive fields: add `InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS`. | ||
|
||
- Jetpack Compose | ||
- Passwords: `KeyboardOptions(keyboardType = KeyboardType.Password, autoCorrect = false)` | ||
- Numeric PINs: `KeyboardOptions(keyboardType = KeyboardType.NumberPassword, autoCorrect = false)` | ||
- Also set a visual transformation where appropriate (e.g., `PasswordVisualTransformation()`). | ||
|
||
- For sensitive but non-password inputs (e.g., security answers), prefer password variations or at minimum disable suggestions (`TYPE_TEXT_FLAG_NO_SUGGESTIONS`, `autoCorrect = false`). | ||
|
||
- Overriding a non-caching type later in code with a generic class type (e.g., setting `TYPE_NUMBER_VARIATION_PASSWORD` and then setting `TYPE_CLASS_NUMBER`). | ||
cpholguera marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
20 changes: 15 additions & 5 deletions
20
demos/android/MASVS-PLATFORM/MASTG-DEMO-0061/MASTG-DEMO-0061.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,41 @@ | ||
--- | ||
platform: android | ||
title: Uses of FLAG_SECURE with semgrep | ||
title: Setting and Clearing FLAG_SECURE in an Activity and Dialog with semgrep | ||
id: MASTG-DEMO-0061 | ||
code: [kotlin] | ||
test: MASTG-TEST-0291 | ||
--- | ||
|
||
### Sample | ||
|
||
The sample uses the `addFlags` method to set the `FLAG_SECURE` window flag on an activity that displays sensitive data. | ||
The sample demonstrates multiple ways of preventing screenshots of sensitive content in two Android components: an Activity and a standard Dialog. It also demonstrates incorrect ways of removing the screenshot prevention. | ||
|
||
{{ MastgTest.kt # MastgTest_reversed.java }} | ||
|
||
### Steps | ||
|
||
Let's run our @MASTG-TOOL-0110 rule against the reversed java code. | ||
Let's run our @MASTG-TOOL-0110 rule against the reversed Java code. | ||
|
||
{{ ../../../../rules/mastg-android-sensitive-data-in-screenshot.yml }} | ||
|
||
{{ run.sh }} | ||
|
||
### Observation | ||
|
||
The rule has identified one location in the code file where the app has set the `FLAG_SECURE` window flag using the `addFlags` method. | ||
The rule has identified several locations in the code file where the app sets or clears the `FLAG_SECURE` window flag. | ||
|
||
{{ output.txt }} | ||
|
||
### Evaluation | ||
|
||
This test passes because the app used the `addFlags` method to set the `FLAG_SECURE` window flag on an activity that displays sensitive data. | ||
The test fails because even though the app demonstrates correct protection patterns by setting `FLAG_SECURE` for an Activity and a dialog, it subsequently removes protection by clearing/overwriting `FLAG_SECURE` on both the Activity and the dialog. | ||
|
||
We can see this in `MastgTest_reversed.java`: | ||
|
||
- For the activity: | ||
- it adds the `FLAG_SECURE` flag via `getWindow().addFlags(8192)` (line 35) | ||
- sets it again with `getWindow().setFlags(8192, 8192)` (line 36) | ||
- and then immediately clears it with `getWindow().setFlags(0, 8192)` (line 37) | ||
- For the dialog: | ||
- it sets `window.setFlags(8192, 8192)` (line 42) | ||
- and then calls `window2.clearFlags(8192)` (line 46) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,29 @@ | ||
|
||
|
||
┌────────────────┐ | ||
│ 1 Code Finding │ | ||
└────────────────┘ | ||
┌─────────────────┐ | ||
│ 5 Code Findings │ | ||
└─────────────────┘ | ||
|
||
MastgTest_reversed.java | ||
❱ rules.mastg-android-flag-secure-enable-flags | ||
[MASVS-PLATFORM] Make sure you use this flag for all screens with sensitive data | ||
|
||
32┆ ((Activity) this.context).getWindow().addFlags(8192); | ||
35┆ ((Activity) this.context).getWindow().addFlags(8192); | ||
⋮┆---------------------------------------- | ||
36┆ ((Activity) this.context).getWindow().setFlags(8192, 8192); | ||
|
||
❯❱ rules.mastg-android-flag-secure-clear-flags | ||
[MASVS-PLATFORM] Window clears or overwrites FLAG_SECURE. | ||
|
||
37┆ ((Activity) this.context).getWindow().setFlags(0, 8192); | ||
|
||
❱ rules.mastg-android-flag-secure-enable-flags | ||
[MASVS-PLATFORM] Make sure you use this flag for all screens with sensitive data | ||
|
||
42┆ window.setFlags(8192, 8192); | ||
|
||
❯❱ rules.mastg-android-flag-secure-clear-flags | ||
[MASVS-PLATFORM] Window clears or overwrites FLAG_SECURE. | ||
|
||
46┆ window2.clearFlags(8192); | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.