Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions demos/android/MASVS-PLATFORM/MASTG-DEMO-yyyy/MASTG-DEMO-yyyy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
platform: android
title: App leaking sensitive information to Firebase Analytics
id: MASTG-DEMO-yyyy
code: [kotlin]
test: MASTG-TEST-xxxx
---

## Sample

This sample demonstrates an Android application that inadvertently leaks sensitive user information to Firebase Analytics. The app collects various types of sensitive data, such as user IDs, email addresses, and names, and sends this information to Firebase Analytics.

> Note: To compile the test correctly, you need to include the Firebase Analytics library in the `build.gradle` file. i.e.`implementation("com.google.firebase:firebase-analytics:23.0.0")`.

{{ MastgTest.kt }}

## Steps

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

{{ ../../../../rules/mastg-android-sensitive-data-to-embedded-firebase-analytics.yml }}

{{ run.sh }}

## Observation

The rule detected 8 instances where sensitive data might be sent to Firebase Analytics. The findings include various types of sensitive information, such as user IDs, email addresses, and names, based on the rule's defined pattern.

{{ 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 information, specifically a first and a last name, an email, a user ID, and a secret.
46 changes: 46 additions & 0 deletions demos/android/MASVS-PLATFORM/MASTG-DEMO-yyyy/MastgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.owasp.mastestapp

import android.content.Context
import android.os.Bundle
import com.google.firebase.analytics.FirebaseAnalytics

class MastgTest(private val context: Context) {

fun mastgTest(): String {
val sensitiveString = "d3a447630194bd4b"
val email = "user@example.com"
val firstLast = "John Doe"
val arbitraryUserId = "user12345"

val analytics = FirebaseAnalytics.getInstance(context)

// Test 1: logEvent with bundle
val eventBundle = Bundle().apply {
putString("user_email", email)
putString("full_name", firstLast)
}
analytics.logEvent("event_name", eventBundle)

// Test 2: setUserProperty
analytics.apply {
setUserProperty("name", firstLast)
setUserProperty("email", email)
}

// Test 3: setUserId
analytics.setUserId(arbitraryUserId)

// Test 4: setDefaultEventParameters
val defaultBundle = Bundle().apply {
putString("default_key", sensitiveString)
}
analytics.setDefaultEventParameters(defaultBundle)

return """Sensitive data:
Email: $email
Full Name: $firstLast
User ID: $arbitraryUserId
Sensitive String: $sensitiveString
""".trimIndent()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.owasp.mastestapp;

import android.content.Context;
import android.os.Bundle;
import com.google.firebase.analytics.FirebaseAnalytics;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import kotlin.text.StringsKt;

/* compiled from: MastgTest.kt */
@Metadata(d1 = {"\u0000\u0018\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0018\u0002\n\u0002\b\u0003\n\u0002\u0010\u000e\n\u0000\b\u0007\u0018\u00002\u00020\u0001B\u000f\u0012\u0006\u0010\u0002\u001a\u00020\u0003¢\u0006\u0004\b\u0004\u0010\u0005J\u0006\u0010\u0006\u001a\u00020\u0007R\u000e\u0010\u0002\u001a\u00020\u0003X\u0082\u0004¢\u0006\u0002\n\u0000¨\u0006\b"}, d2 = {"Lorg/owasp/mastestapp/MastgTest;", "", "context", "Landroid/content/Context;", "<init>", "(Landroid/content/Context;)V", "mastgTest", "", "app_debug"}, k = 1, mv = {2, 0, 0}, xi = 48)
/* loaded from: classes3.dex */
public final class MastgTest {
public static final int $stable = 8;
private final Context context;

public MastgTest(Context context) {
Intrinsics.checkNotNullParameter(context, "context");
this.context = context;
}

public final String mastgTest() {
FirebaseAnalytics analytics = FirebaseAnalytics.getInstance(this.context);
Intrinsics.checkNotNullExpressionValue(analytics, "getInstance(...)");
Bundle eventBundle = new Bundle();
eventBundle.putString("user_email", "user@example.com");
eventBundle.putString("full_name", "John Doe");
analytics.logEvent("event_name", eventBundle);
analytics.setUserProperty("name", "John Doe");
analytics.setUserProperty("email", "user@example.com");
analytics.setUserId("user12345");
Bundle defaultBundle = new Bundle();
defaultBundle.putString("default_key", "d3a447630194bd4b");
analytics.setDefaultEventParameters(defaultBundle);
return StringsKt.trimIndent("Sensitive data:\n\t\t\tEmail: user@example.com\n\t\t\tFull Name: John Doe\n\t\t\tUser ID: user12345\n\t\t\tSensitive String: d3a447630194bd4b\n\t\t\t");
}
}
26 changes: 26 additions & 0 deletions demos/android/MASVS-PLATFORM/MASTG-DEMO-yyyy/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@


┌─────────────────┐
│ 8 Code Findings │
└─────────────────┘

MastgTest_reversed.java
❯❱ rules.mastg-android-sensitive-data-to-embedded-firebase-analytics
[MASVS-PLATFORM-2] Sensitive data is being sent to Firebase Analytics

26┆ eventBundle.putString("user_email", "user@example.com");
⋮┆----------------------------------------
27┆ eventBundle.putString("full_name", "John Doe");
⋮┆----------------------------------------
28┆ analytics.logEvent("event_name", eventBundle);
⋮┆----------------------------------------
29┆ analytics.setUserProperty("name", "John Doe");
⋮┆----------------------------------------
30┆ analytics.setUserProperty("email", "user@example.com");
⋮┆----------------------------------------
31┆ analytics.setUserId("user12345");
⋮┆----------------------------------------
33┆ defaultBundle.putString("default_key", "d3a447630194bd4b");
⋮┆----------------------------------------
34┆ analytics.setDefaultEventParameters(defaultBundle);

1 change: 1 addition & 0 deletions demos/android/MASVS-PLATFORM/MASTG-DEMO-yyyy/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-sensitive-data-to-embedded-firebase-analytics.yml ./MastgTest_reversed.java > output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
rules:
- id: mastg-android-sensitive-data-to-embedded-firebase-analytics
severity: WARNING
languages: [java]
metadata:
summary: "Detects sensitive data being sent to Firebase Analytics."
message: "[MASVS-PLATFORM-2] Sensitive data is being sent to Firebase Analytics"
mode: taint
pattern-sources:
- patterns:
- pattern: '"$SECRET"'
- metavariable-analysis:
metavariable: $SECRET
analyzer: entropy
- patterns:
- pattern: '"$EMAIL"'
- metavariable-regex:
metavariable: $EMAIL
regex: (?i)[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}
- patterns:
- pattern: '"$FULLNAME"'
- metavariable-regex:
metavariable: $FULLNAME
regex: (?i)[A-Z][a-z]+ [A-Z][a-z]+
- patterns:
- pattern: '"$UID"'
- metavariable-regex:
metavariable: $UID
regex: (?i)user[0-9]+
pattern-sinks:
- pattern: $FA.logEvent($EVT, $ARG)
- pattern: $FA.setUserProperty($NAME, $ARG)
- pattern: $FA.setUserId($ARG)
- pattern: $FA.setDefaultEventParameters($ARG)
- pattern: $BUNDLE.putString($K, $V)
pattern-inside: |
...;
$FA.logEvent($EVT, $BUNDLE);
...;
pattern-propagators:
- pattern: $BUNDLE.putString($K, $V)
from: $V
to: $BUNDLE
6 changes: 3 additions & 3 deletions techniques/android/MASTG-TECH-0108.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ In taint analysis, data flows from a "source" to a "sink". A source is where sen

In large applications, manual information flow analysis can be very time-consuming and inaccurate. Taint analysis automates this, with two main methods: static and dynamic. The former examines code without running it, offering broad coverage but potentially yielding false positives. In contrast, dynamic analysis observes real-time application execution, providing actual context but possibly overlooking untriggered issues. A thorough comparison of these techniques is beyond this section's scope.

There are multiple tools which perform taint analysis on native code, including [Triton](https://github.com/jonathansalwan/Triton "Triton") and [bincat](https://github.com/airbus-seclab/bincat "bincat"). However, in this section, we'll primarily focus on Android Java code and utilize @MASTG-TOOL-0099 for the taint analysis. Another notable tool supporting taint analysis for Android apps is [GDA](https://github.com/charles2gan/GDA-android-reversing-Tool/wiki/GDA-Static-Taint-Analysis "GDA").
There are multiple tools which perform taint analysis on native code, including [Triton](https://github.com/jonathansalwan/Triton "Triton"), [bincat](https://github.com/airbus-seclab/bincat "bincat"), and @MASTG-TOOL-0110. However, in this section, we'll primarily focus on Android Java code and utilize @MASTG-TOOL-0099 for the taint analysis. Another notable tool supporting taint analysis for Android apps is [GDA](https://github.com/charles2gan/GDA-android-reversing-Tool/wiki/GDA-Static-Taint-Analysis "GDA").

For our demonstration, we'll use the @MASTG-TOOL-0099 command line tool to perform taint analysis on the [InsecureShop v1.0](https://github.com/hax0rgb/InsecureShop/releases/tag/v1.0 "InsecureShop") application.

The InsecureShop app accepts a username and password as input and stores them in the app's shared preferences. In our taint analysis, we're interested in how this stored username and password are used. In this context, the username and password are the sensitive information, and reading from shared preferences is the source. The sink in this analysis could be various operations, such as sending info over the network, transmitting info via an `Intent`, or storing info in an external file.

To use FlowDroid, firstly, we need to provide an input list of potential sources and sinks to evaluate for. In our case, _reading from shared preferences_ will be the source, while _adding parameters to an `Intent`_ will be the sink. The configuration file will look as follows (we'll name it "source_sink.txt"):
To use FlowDroid, firstly, we need to provide an input list of potential sources and sinks to evaluate. In our case, _reading from shared preferences_ will be the source, while _adding parameters to an `Intent`_ will be the sink. The configuration file will look as follows (we'll name it "source_sink.txt"):

```Jimple
<android.content.SharedPreferences: java.lang.String getString(java.lang.String, java.lang.String)> -> _SOURCE_
Expand Down Expand Up @@ -68,4 +68,4 @@ fun onSendData(view: View) {
}
```

Taint analysis is especially beneficial for automating data flow analysis in intricate applications. However, given the complexity of some apps, the accuracy of such tools can vary. Thus, it's essential for reviewers to find a balance between the accuracy of tools and the time spent on manual analysis.
Taint analysis is especially beneficial for automating data flow analysis in intricate applications. However, given the complexity of some apps, the accuracy of such tools can vary. Thus, reviewers need to find a balance between the accuracy of tools and the time spent on manual analysis.
35 changes: 35 additions & 0 deletions tests-beta/android/MASVS-PLATFORM/MASTG-TEST-xxxx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
platform: android
title: Sensitive Data Leaked via Embedded Libraries
id: MASTG-TEST-xxxx // TODO
type: [static, dynamic]
weakness: MASWE-xxxA // TODO see https://github.com/OWASP/maswe/pull/11
prerequisites:
- identify-sensitive-data
- identify-embedded-libraries-with-network-access // TODO makes sense? get feedback
profiles: [L1, L2]
---

## Overview

This test case focuses on identifying potentially sensitive data inadvertently leaked through embedded third-party libraries used by the application. For example, an app might use a third-party analytics SDK to track user behavior, but if the SDK is not properly configured, it could inadvertently send sensitive information (like PIIs - Personal Identifiable Information, or secrets) to that third-party service.

## Steps

1. Generate an SBOM.
- For black-box testing, you can use tools like @MASTG-TOOL-0130 or @MASTG-TOOL-0134 with @MASG-TECH-0130 or @MASTG-TECH-0131 to identify all embedded/3rd-party libraries used by the app.
- For grey/white-box testing, you can manually review the app's build files (like `build.gradle`) to identify dependencies.
2. Shortlist the embedded/3rd-party libraries' APIs which have network functionality and that should not handle sensitive information. Look for permissions like `INTERNET` or `ACCESS_NETWORK_STATE`.
- For black-box testing, you can research those libraries online or their codebase to see if they have network functionality.
- For gray/white-box testing, you can manually review the app's merged manifest file in Android Studio or by manually generating with a command like `./gradlew app:processDebugManifest` and then inspecting the file in `app/build/intermediates/merged_manifests/debug/AndroidManifest.xml`. If possible, you can review the app's codebase.
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have always focused on black box testing but recently also included some white box tests such as the SBOM related ones which are labeled as “manual” type if I remember properly. If we’re gonna do this we should keep the manual test separate.

For now, let’s focus on black box testing in this PR.

But please create an issue for this manual test and for creating a technique about inspecting the merged manifest in Android Studio which can be very interesting for other tests as well.

Copy link
Collaborator Author

@Diolor Diolor Sep 29, 2025

Choose a reason for hiding this comment

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

thanks for the direction 👍

Created #3489

3. Identify common APIs of those libraries that are used to send data to their servers.
- Use @MASTG-TECH-0110, potentially with @MASTG-TOOL-0108, to identify sensitive data pass to the APIs.
- Alternatively use you can perform dynamic analysis by intercepting traffic using @MASTG-TECH-0120 and @MASTG-TECH-0121. Once you route the traffic through the interception proxy, you can try to sniff the traffic that passes between the app and app's known servers. All app requests that aren't sent directly to the app's server on which the main function is hosted should be evaluated.
Copy link
Collaborator

@cpholguera cpholguera Sep 27, 2025

Choose a reason for hiding this comment

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

We already have https://mas.owasp.org/MASTG/tests/android/MASVS-PRIVACY/MASTG-TEST-0206/ which should be addressing Could be enhanced with a new title mentioning “undeclared PII” instead of sensitive data.

This test here would focus on the limitation of MASTG-TEST-0206: “Note that this test does not provide any code locations where the sensitive data is being sent over the network”.

We could have two approaches maybe:

  • the one you’re proposing (static). We should highlight the “downside” of this approach which is that you need to have some kind of knowledge base of all existing libraries and the relevant functions where they could put PII. We should discuss this, it sounds like a significant downside.
  • use Frida to hook all network functions (and try to detect PII in their calls) and use the backtraces to find out which component is sending what PII (this should also include the corresponding network domains). This should provide much greater coverage while staying sufficiently generic. Not 100% perfect but pretty good.


## Observation

The output should contain a list of locations where sensitive information is passed to embedded/3rd-party libraries or a list of network requests to third-party servers that contain sensitive information.

## Evaluation

The test case fails if sensitive data is found to be passed to embedded/3rd-party libraries that have network functionality or if network requests to third-party servers contain sensitive information.
10 changes: 6 additions & 4 deletions tests/android/MASVS-STORAGE/MASTG-TEST-0004.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ masvs_v1_id:
masvs_v2_id:
- MASVS-STORAGE-2
platform: android
title: Determining Whether Sensitive Data Is Shared with Third Parties via Embedded
Services
title: Determining Whether Sensitive Data Is Shared with Third Parties via Embedded Services
masvs_v1_levels:
- L1
- L2
profiles: [L1, L2]
status: deprecated
covered_by: [MASTG-TEST-xxxx] // TODO
deprecation_note: New version available in MASTG V2
---

## Overview

## Static Analysis

To determine whether API calls and functions provided by the third-party library are used according to best practices, review their source code, requested permissions and check for any known vulnerabilities.
To determine whether API calls and functions provided by the third-party library are used according to best practices, review their source code, requested permissions, and check for any known vulnerabilities.

All data that's sent to third-party services should be anonymized to prevent exposure of PII (Personal Identifiable Information) that would allow the third party to identify the user account. No other data (such as IDs that can be mapped to a user account or session) should be sent to a third party.

## Dynamic Analysis

Check all requests to external services for embedded sensitive information.
To intercept traffic between the client and server, you can perform dynamic analysis by launching a [Machine-in-the-Middle (MITM)](../../../Document/0x04f-Testing-Network-Communication.md#intercepting-network-traffic-through-mitm) attack with @MASTG-TOOL-0077 or @MASTG-TOOL-0079. Once you route the traffic through the interception proxy, you can try to sniff the traffic that passes between the app and server. All app requests that aren't sent directly to the server on which the main function is hosted should be checked for sensitive information, such as PII in a tracker or ad service.
To intercept traffic between the client and server, you can perform dynamic analysis by launching a [Machine-in-the-Middle (MITM)](../../../Document/0x04f-Testing-Network-Communication.md#intercepting-network-traffic-through-mitm) attack with @MASTG-TOOL-0077 or @MASTG-TOOL-0079. Once you route the traffic through the interception proxy, you can try to sniff the traffic that passes between the app and server. All app requests that aren't sent directly to the server on which the main function is hosted should be checked for sensitive information, such as PII, in a tracker or ad service.
Loading