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

---
platform: android
title: WebView Ignoring TLS Errors in onReceivedSslError
id: MASTG-DEMO-0056
code: [kotlin]
test: MASTG-TEST-0284
---

## Sample

This sample connects to <https://tlsexpired.no>, which has an expired SSL certificate, and demonstrates how a WebView ignores SSL/TLS errors by overriding the `onReceivedSslError(...)` method without proper validation. The app calls `proceed()` unconditionally, which allows the connection to continue even when there are TLS errors.

{{ MastgTestWebView.kt # MastgTestWebView_reversed.java }}

## Steps

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

{{ ../../../../rules/mastg-android-network-onreceivedsslerror.yml }}

{{ run.sh }}

## Observation

The rule identified one instance of the use of the `onReceivedSslError(...)` in the code.

{{ output.txt }}

## Evaluation

The test fails because the app uses a WebView that calls `proceed()` in its `onReceivedSslError(...)` method without validating the TLS error at all. You can manually validate this in the app's reverse-engineered code by inspecting the provided code locations.

In this case:

```java
            public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
                ...
                String message = this.this$0.getSslErrorMessage(error);
                Log.e("MastgTestWebView", "SSL errors onReceivedSslError: " + message);
                Log.e("MastgTestWebView", error.toString());
                handler.proceed();
            }
```

By doing this, the app is effectively ignoring every TLS error even though we can see that the expired certificate error is logged (see @MASTG-TECH-0009):

{{ logcat.txt }}
OWASP Mobile Application Security Testing Guide: logcat

[ERROR:ssl_client_socket_impl.cc(877)] handshake failed; returned -1, SSL error code 1, net_error -201
SSL errors onReceivedSslError: The date of the certificate is invalid.
primary error: 4 certificate: Issued to: OU=Insubordinate,O=Insecure CA,1.2.840.113549.1.9.1=#161a696e[PII_REDACTED]6540746c737265766f636174696f6e2e6f7267,C=NO,ST=Buskerud,CN=tlsexpired.no;
Issued by: 1.2.840.113549.1.9.1=#16126a6f68616e[PII_REDACTED]657465722e636f6d,CN=sydseter.com,OU=Sydseter,O=Sydseter,L=Drammen,ST=Drammen,C=NO;
 on URL: https://tlsexpired.no/
OWASP Mobile Application Security Testing Guide: output

                  
                  
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
                           
    MastgTest_reversed.java
    ❯❱ rules.mastg-android-network-checkservertrusted
          Improper Server Certificate verification detected.
                                                            
           92┆ @Override // javax.net.ssl.X509TrustManager
           93┆ public void checkServerTrusted(X509Certificate[] chain, String authType) {
           94┆ }
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0054

---
platform: android
title: Use of a TrustManager that Does Not Validate Certificate Chains
id: MASTG-DEMO-0054
code: [kotlin]
test: MASTG-TEST-0282
---

## Sample

This sample connects to <https://tlsexpired.no>, which has an expired certificate, to demonstrate the insecure use of a custom `TrustManager` that ignores certificate chain validity. It does this by overriding the `checkServerTrusted(...)` method and leaving it empty, which effectively disables certificate validation.

{{ MastgTest.kt # MastgTest_reversed.java }}

If the app wouldn't use the insecure `TrustManager`, you would see this message:

```txt
[https://tlsexpired.no] Error: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
```

## Steps

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

{{ ../../../../rules/mastg-android-network-checkservertrusted.yml }}

{{ run.sh }}

## Observation

The rule identified one instance in the code where `checkServerTrusted(...)` is used without exception handling.

{{ output.txt }}

## Evaluation

The test fails because of the presence of the `checkServerTrusted(...)` method on in the `TrustManager` implementation, as well as the absence of exceptions being thrown.
OWASP Mobile Application Security Testing Guide: output

                  
                  
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
                           
    MastgTest_reversed.java
    ❯❱ rules.mastg-android-network-hostname-verification
          Improper server hostname verification detected
                                                        
           69┆ connection.setHostnameVerifier(new HostnameVerifier() { // from class:
               org.owasp.mastestapp.MastgTest$$ExternalSyntheticLambda0              
           70┆     @Override // javax.net.ssl.HostnameVerifier
           71┆     public final boolean verify(String str, SSLSession sSLSession) {
           72┆         return MastgTest.fetchUrl$lambda$1(str, sSLSession);
           73┆     }
           74┆ });
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0055

---
platform: android
title: Use of the HostnameVerifier that Allows Any Hostname
id: MASTG-DEMO-0055
code: [kotlin]
test: MASTG-TEST-0283
---

## Sample

This sample connects to a URL with an subject alternative name that does not match the hostname and configures a `HostnameVerifier` that allows any hostname.

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

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

{{ ../../../../rules/mastg-android-network-hostname-verification.yml }}

{{ run.sh }}

## Observation

The rule identified one instance of the use of the `HostnameVerifier` in the code.

{{ output.txt }}

## Evaluation

The test fails because the app uses a `HostnameVerifier` that allows any hostname.

In this case, since the rule only checks for the presence of a `HostnameVerifier` and does not validate the implementation of the verifier, you need to manually validate the app's reverse-engineered code and inspect the provided code locations.

The rule points to MastgTest_reversed.java, where we can see the following code:

```java
            connection.setHostnameVerifier(new HostnameVerifier() { // from class: org.owasp.mastestapp.MastgTest$$ExternalSyntheticLambda0
                @Override // javax.net.ssl.HostnameVerifier
                public final boolean verify(String str, SSLSession sSLSession) {
                    return MastgTest.fetchUrl$lambda$1(str, sSLSession);
                }
            });
            ...

    /* JADX INFO: Access modifiers changed from: private */
    public static final boolean fetchUrl$lambda$1(String hostname, SSLSession sSLSession) {
        Log.w("HOSTNAME_VERIFIER", "Insecurely allowing host: " + hostname);
        return true;
    }
```

We can see how:

- the app sets a custom `HostnameVerifier` on the HTTPS connection.
- the verifier calls `fetchUrl$lambda$1`, which logs a warning and returns `true`.

This way we can conclude that the hostname verification does **not** properly validate that the server's hostname matches the certificate subject alternative name.
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 3 Code Findings │
└─────────────────┘
                           
    MastgTest_reversed.java
     ❱ rules.mastg-android-ssl-socket-hostnameverifier
           35┆ SocketFactory socketFactory = SSLSocketFactory.getDefault();
            ⋮┆----------------------------------------
           37┆ SSLSocketFactory sslSocketFactory = (SSLSocketFactory) socketFactory;
            ⋮┆----------------------------------------
           38┆ Socket createSocket = sslSocketFactory.createSocket("wrong.host.badssl.com", 443);
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0048

---
title: SSLSocket Connection to Wrong Host Server Allowed by Lack of HostnameVerifier
platform: android
id: MASTG-DEMO-0048
test: MASTG-TEST-0234
code: [kotlin]
kind: fail
---

## Overview

The following sample code demonstrates how to connect to a @MASTG-TOOL-0143 server that delivers a certificate with a **wrong or invalid hostname** using `SSLSocket`, which inherently [doesn't perform any hostname validation checks](https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket).

**Note:** The connection succeeds even if the app has a fully secure Network Security Configuration (NSC) in place because `SSLSocket` is not affected by it.

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

1. Reverse engineer the app (@MASTG-TECH-0017).
2. Run a static analysis (@MASTG-TECH-0014) tool and look for all usages of `SSLSocket` and `HostnameVerifier`.

{{ ../../../../rules/mastg-android-ssl-socket-hostnameverifier.yml }}

{{ run.sh }}

## Observation

The output contains a list of locations where `SSLSocket` and `HostnameVerifier` are used.

{{ output.txt }}

## Evaluation

The test case fails due to the missing `HostnameVerifier`.

**Note:** If the app were to use a `HostnameVerifier`, the **connection would abort** with an exception like the following, which can be read in the logcat output:

```plaintext
javax.net.ssl.SSLException: Hostname verification failed for host: wrong.host.badssl.com
```
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 5 Code Findings │
└─────────────────┘
                           
    MastgTest_reversed.java
     ❱ rules.mastg-android-ssl-socket-hostnameverifier
           42┆ SocketFactory socketFactory = SSLSocketFactory.getDefault();
            ⋮┆----------------------------------------
           44┆ SSLSocketFactory sslSocketFactory = (SSLSocketFactory) socketFactory;
            ⋮┆----------------------------------------
           45┆ Socket createSocket = sslSocketFactory.createSocket("wrong.host.badssl.com", 443);
            ⋮┆----------------------------------------
           49┆ hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
            ⋮┆----------------------------------------
           61┆ if (!hostnameVerifier.verify("wrong.host.badssl.com", session)) {
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0049

---
title: SSLSocket Connection to Wrong Host Server Blocked by HostnameVerifier
platform: android
id: MASTG-DEMO-0049
test: MASTG-TEST-0234
code: [kotlin]
kind: pass
---

## Overview

The following sample code demonstrates how to connect to a @MASTG-TOOL-0143 server that delivers a certificate with a **wrong or invalid hostname** using `SSLSocket` which inherently [doesn't perform any hostname validation checks](https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket).

However, the code implements a custom `HostnameVerifier` that performs hostname verification, thus blocking the connection to the server with the wrong hostname.

{{ MastgTest.kt # MastgTest_reversed.java }}

## Steps

1. Reverse engineer the app (@MASTG-TECH-0017).
2. Run a static analysis (@MASTG-TECH-0014) tool and look for all usages of `SSLSocket` and `HostnameVerifier`.

{{ ../../../../rules/mastg-android-ssl-socket-hostnameverifier.yml }}

{{ run.sh }}

## Observation

The output contains a list of locations where `SSLSocket` and `HostnameVerifier` are used.

{{ output.txt }}

## Evaluation

The test case passes due to the use of a `HostnameVerifier`.

As expected, **the connection aborts** as you can see in the logcat output which contains the following exception:

```plaintext
javax.net.ssl.SSLException: Hostname verification failed for host: wrong.host.badssl.com
```
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 2 Code Findings │
└─────────────────┘
                                
    AndroidManifest_reversed.xml
     ❱ rules.mastg-android-overlay-protection-hide-overlay-windows-permission
          [MASVS-PLATFORM-3] HIDE_OVERLAY_WINDOWS permission is declared, required to use
          setHideOverlayWindows                                                          
                                                                                         
           14┆ <uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS"/>
                           
    MastgTest_reversed.java
     ❱ rules.mastg-android-overlay-protection-sethideoverlaywindows
          [MASVS-PLATFORM-3] setHideOverlayWindows is used to prevent overlay windows from appearing over this
          window                                                                                              
                                                                                                              
           55┆ activity.getWindow().setHideOverlayWindows(true);
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0105

---
platform: android
title: Activity-Level Overlay Protection Using setHideOverlayWindows
id: MASTG-DEMO-0105
code: [kotlin, java, xml]
test: MASTG-TEST-0340
tools: [semgrep]
kind: pass
---

## Sample

The sample shows an app that uses `setHideOverlayWindows(true)` at the activity level (available from Android 12, API level 31) and declares the required `HIDE_OVERLAY_WINDOWS` permission in the manifest. Unlike the view-level protections in @MASTG-DEMO-0103, this approach prevents any overlay window from appearing over the entire activity.

{{ MastgTest.kt # MastgTest_reversed.java # AndroidManifest.xml # AndroidManifest_reversed.xml }}

## Steps

Let's run our @MASTG-TOOL-0110 rule against the decompiled code and the reversed manifest to detect the overlay protection mechanisms.

{{ ../../../../rules/mastg-android-overlay-protection.yml }}

{{ run.sh }}

## Observation

The rule detected the `setHideOverlayWindows` call in the decompiled code and the `HIDE_OVERLAY_WINDOWS` permission in the manifest:

{{ output.txt }}

## Evaluation

The test passes because the app implements activity-level overlay protection:

- The `setHideOverlayWindows(true)` call (detected in the code output) instructs the system to hide any `TYPE_APPLICATION_OVERLAY` windows when this activity is in the foreground, effectively preventing overlay attacks on all UI elements in the activity.
- The `HIDE_OVERLAY_WINDOWS` permission (detected in the manifest output) is required to use `setHideOverlayWindows` on Android 12 (API level 31) and above.

This is a stronger protection than the view-level approach shown in @MASTG-DEMO-0103, which requires adding protection to every sensitive view individually.
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0062

---
platform: android
title: Enabling Screenshots in Recents via setRecentsScreenshotEnabled with semgrep
id: MASTG-DEMO-0062
code: [kotlin]
test: MASTG-TEST-0292
status: placeholder
note: This demo shows how to detect the use of `setRecentsScreenshotEnabled(true)` in Android apps using Semgrep.
---
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0082

---
platform: android
title: WebView WebStorage Cleanup
id: MASTG-DEMO-0082
code: [kotlin]
test: MASTG-TEST-0320
---

## Sample

The code snippet below shows a sample that uses a WebView to store sensitive data in the cache and then performs a cleanup with `WebStorage` API.

The sensitive data is stored using `localStorage.setItem` in the inline HTML loaded into the WebView. The values used are:

- `'sensitive_token'` with value `'SECRET_TOKEN_123456'`.
- `'driving_license_id'` with value `'DL-987654321'`.

{{ MainActivityWebView.kt # MastgTestWebView.kt # AndroidManifest.xml }}

## Steps

1. Install the app on a device (@MASTG-TECH-0005)
2. Make sure you have @MASTG-TOOL-0001 installed on your machine and the frida-server running on the device
3. Run `run.sh` to spawn the app with Frida
4. Click the **Start** button in the app
5. Wait for the Frida script to capture the WebView cleanup calls
6. Stop the script by quitting the Frida CLI
7. Use @MASTG-TECH-0002 to search the contents of the `/data/data/<app_package>/app_webview/` directory for the sensitive data used in the WebView.

{{ script.js # run.sh }}

## Observation

In the output we can see all instances of `deleteAllData()` of `WebStorage` called at runtime:

{{ output.json }}

We can also see that the output of the `adb shell grep` command shows no matches for the sensitive data used in the WebView:

{{ output_adb_deletion_succeeded.txt }}

## Evaluation

The test **passes** as the application properly cleans up all storage data from the WebView cache using the `WebStorage` API.

If you want to demonstrate the failure case, you can comment out the `WebStorage.getInstance().deleteAllData()` line in the code and rerun the test. In this case, the test **fails** because the sensitive data remains in the WebView storage directory after closing the app.

{{ output_adb_deletion_failed.txt }}
OWASP Mobile Application Security Testing Guide: output adb deletion failed

adb shell 'grep -nri -E "SECRET_TOKEN_123456|DL-987654321" /data/data/org.owasp.mastestapp/app_webview'
Binary file /data/data/org.owasp.mastestapp/app_webview/Default/Local Storage/leveldb/000003.log matches
Binary file /data/data/org.owasp.mastestapp/app_webview/Default/Local Storage/leveldb/000003.log matches
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0063

---
platform: android
title: Incorrectly Preventing Screenshots with SecureFlagPolicy in Compose Dialogs with semgrep
id: MASTG-DEMO-0063
code: [kotlin]
test: MASTG-TEST-0293
status: placeholder
note: This demo shows how to detect the incorrect use of `SecureFlagPolicy` in Jetpack Compose dialogs using Semgrep.
---
OWASP Mobile Application Security Testing Guide: output

                   
                   
┌─────────────────┐
│ 4 Code Findings │
└─────────────────┘
                                  
    MastgTestWebView_reversed.java
     ❱ rules.mastg-android-webview-settings
          [MASVS-PLATFORM-2] Detected WebView settings.
                                                       
           29┆ WebSettings $this$mastgTest_u24lambda_u240 = webView.getSettings();
            ⋮┆----------------------------------------
           30┆ $this$mastgTest_u24lambda_u240.setJavaScriptEnabled(true);
            ⋮┆----------------------------------------
           31┆ $this$mastgTest_u24lambda_u240.setAllowFileAccess(true);
            ⋮┆----------------------------------------
           32┆ $this$mastgTest_u24lambda_u240.setAllowFileAccessFromFileURLs(true);
OWASP Mobile Application Security Testing Guide: MASTG DEMO 0032

---
platform: android
title: Uses of WebViews Allowing Local File Access with semgrep
id: MASTG-DEMO-0032
code: [kotlin]
test: MASTG-TEST-0252
---

## Sample

This sample demonstrates the use of WebViews allowing local file access in an Android app and how an attacker could exploit these settings to exfiltrate sensitive data from the app's internal storage using `file://` URIs.

In this demo we focus on the static analysis of the code using semgrep and don't run the app nor the attacker server.

See @MASTG-DEMO-0031 for all the details about the sample and the attack.

{{ MastgTestWebView.kt # AndroidManifest.xml }}

## Steps

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

{{ ../../../../rules/mastg-android-webview-allow-local-access.yml }}

{{ run.sh }}

## Observation

The output shows all WebView settings found in the code.

{{ output.txt }}

## Evaluation

The test **fails** due to the following WebView settings being configured:

{{ evaluation.txt }}

All these settings are explicitly set to `true` in the code, otherwise, they would remain at their default values (`false`).
OWASP Mobile Application Security Testing Guide: output


[*] WebView.getSettings() called on instance: android.webkit.WebView{72e86a8 VFEDHVC.. ......I. 0,0-0,0}

Backtrace:
android.webkit.WebView.getSettings(Native Method)
org.owasp.mastestapp.MastgTestWebView.mastgTest(MastgTestWebView.kt:26)
org.owasp.mastestapp.MainActivityWebViewKt$WebViewScreen$1$1$2$1.invoke(MainActivityWebView.kt:88)
org.owasp.mastestapp.MainActivityWebViewKt$WebViewScreen$1$1$2$1.invoke(MainActivityWebView.kt:85)
androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:343)
androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1.invoke(AndroidView.android.kt:274)
androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1.invoke(AndroidView.android.kt:273)
androidx.compose.ui.viewinterop.AndroidView_androidKt$AndroidView$$inlined$ComposeNode$1.invoke(Composables.kt:254)



[*] Triggering enumeration after getSettings() call...

[*] Finished enumerating WebView instances!

[*] Found WebView instance: android.webkit.WebView{72e86a8 VFEDHVC.. ........ 0,0-904,1796}
	[+] JavaScriptEnabled: true
	[+] AllowFileAccess: true
	[+] AllowFileAccessFromFileURLs: true
	[+] AllowUniversalAccessFromFileURLs: false
	[+] AllowContentAccess: true
	[+] MixedContentMode: 1
	[+] SafeBrowsingEnabled: true
OWASP Mobile Application Security Testing Guide: output


[*] WebView.getSettings() called on instance: android.webkit.WebView{5c7fac1 VFEDHVC.. ......I. 0,0-0,0}

Backtrace:
android.webkit.WebView.getSettings(Native Method)
org.owasp.mastestapp.MastgTestWebView.mastgTest(MastgTestWebView.kt:25)
org.owasp.mastestapp.MainActivityWebViewKt$WebViewScreen$1$1$2$1.invoke(MainActivityWebView.kt:88)
org.owasp.mastestapp.MainActivityWebViewKt$WebViewScreen$1$1$2$1.invoke(MainActivityWebView.kt:85)
androidx.compose.ui.viewinterop.ViewFactoryHolder.<init>(AndroidView.android.kt:343)
androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1.invoke(AndroidView.android.kt:274)
androidx.compose.ui.viewinterop.AndroidView_androidKt$createAndroidViewNodeFactory$1.invoke(AndroidView.android.kt:273)
androidx.compose.ui.viewinterop.AndroidView_androidKt$AndroidView$$inlined$ComposeNode$1.invoke(Composables.kt:254)



[*] Triggering enumeration after getSettings() call...

[*] Finished enumerating WebView instances!

[*] Found WebView instance: android.webkit.WebView{5c7fac1 VFEDHVC.. ........ 0,0-904,1796}
	[+] JavaScriptEnabled: true
	[+] AllowFileAccess: false
	[+] AllowFileAccessFromFileURLs: false
	[+] AllowUniversalAccessFromFileURLs: true
	[+] AllowContentAccess: true
	[+] MixedContentMode: 1
	[+] SafeBrowsingEnabled: true
OWASP Mobile Application Security Testing Guide: output

                  
                  
┌────────────────┐
│ 1 Code Finding │
└────────────────┘
                                
    AndroidManifest_reversed.xml
     ❱ rules.mastg-android-system-alert-window-permission
          [MASVS-PLATFORM-3] SYSTEM_ALERT_WINDOW permission is declared, enabling the app to draw overlays
          over other apps                                                                                 
                                                                                                          
           14┆ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>