As a bug hunter, are your bug bounty reports getting rejected because you don't use a "malicious" Proof of Concept (PoC) app to exploit the vulnerabilities?
As a security engineer, do you struggle validating bug bounty reports and performing regression testing?
I've got you covered!
Rooting your device is not required.
For more tips and tricks check my Android penetration testing cheat sheet.
Built with Android Studio v2024.3.2 (64-bit) (JDK 17) and tested on Samsung Galaxy Note S20 Ultra with Android OS v13.0 (Tiramisu).
Made for educational purposes. I hope it will help!
Future plans:
- add an option to auto-build all content provider URIs and deep links for easier use
- add an option to bind to a service,
- add array type support for
Intent.putExtra()
, - add a capability to pass overlay button clicks to an underlying view,
- hide soft keyboard when user taps outside input,
- create UI to chain multiple exploitation steps after successful deep link callback hijacking,
- showcase PoCs for already disclosed intent injection bug bounty reports,
- add more tests / attacks.
APK name: Malware v2.5
Package name: com.kira.malware
Min SDK: 26
Target SDK: 35
Exported activities:
com.kira.malware.activities.MainActivity
com.kira.malware.activities.HiddenActivity
You may see dialogs asking you to grant the following permissions:
android.permission.READ_EXTERNAL_STORAGE
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.POST_NOTIFICATIONS
android.settings.action.MANAGE_OVERLAY_PERMISSION
android.settings.ACCESSIBILITY_SETTINGS
URIs for internal QA testing:
kira://hidden
content://com.kira.malware.TestFileProvider/files/test.txt
content://com.kira.malware.TestSQLiteProvider
Tip #1: Read and modify files of another app.
Tip #2: Read world-readable shared preferences of another app.
Figure 1 - File System
Tip #1: List protected or exported components of another app.
Tip #2: Request a custom permission defined by another app by declaring it in this app's AndroidManifest.xml
, then rebuild the APK - this works only if the permission's protection level is not signature
<permission
android:name="com.someapp.dev.CUSTOM_PERMISSION"
android:protectionLevel="normal" />
<uses-permission android:name="com.someapp.dev.CUSTOM_PERMISSION" />
Tip #2: List user installed or system packages.
Figure 2 - Enumeration
Tip #1: Test an intent filter of another app.
Tip #2: Send an intent to another app to bypass its biometrics / security.
Tip #3: Send an intent to another app to bypass its biometrics / security by triggering its push notification manager, then manually opening the received push notification.
Tip #4: Send an intent to another app to poison its widget.
Tip #5: Send a [pending] intent to another app multiple times to cause DoS.
Tip #6: Send a mutable pending intent to another app to extract subsequently added intent extras.
Tip #7: Access a protected component, such as a file or SQLite content provider of another app, by exploiting its exported (proxy) component.
**Tip #8:**Test a deep link of another app.
Tip #9: Hijack a deep link of another app by specifying it in this app's AndroidManifest.xml
under HiddenActivity, then rebuild the APK.
<data
android:host="hidden"
android:scheme="kira" />
Tip #10: Perform a battering ram attack on a deep link or content provider URI of another app by adding </payload>
placeholder into the intent's URI.
The following applies only to the proxy intent
extras:
- If the value is a string equal to
targetPendingIntent
:- the entire value will be replaced with an
PendingIntent
object oftarget intent
, - and
Intent.putParcelable()
will be used.
- the entire value will be replaced with an
- If the value is a string equal to
targetIntent
:- the entire value will be replaced with an
Intent
object oftarget intent
, - and
Intent.putParcelable()
will be used.
- the entire value will be replaced with an
- If the value is a string containing
targetIntentToUri
:- all matching parts will be replaced with
Intent.toUri(Intent.URI_INTENT_SCHEME)
oftarget intent
.
- all matching parts will be replaced with
- If the value is a string containing
targetIntentToUriUnsafe
:- all matching parts will be replaced with
Intent.toUri(Intent.URI_ALLOW_UNSAFE)
oftarget intent
.
- all matching parts will be replaced with
The following applies on both the proxy intent
and target intent
extras:
- To use the file content provider callback:
- add an intent extra with the type
string
, - key
HiddenActivity
, - and value
fileProvider
.
- add an intent extra with the type
- To use the SQLite content provider callback:
- add an intent extra with the type
string
, - key
HiddenActivity
, - and value
sqLiteProvider
.
- add an intent extra with the type
- To auto-close the callback activity on success:
- add an intent extra with the type
string
, - key
HiddenActivity
, - and value
closeOnSuccess
.
- add an intent extra with the type
- To auto-close the callback activity on error:
- add an intent extra with the type
string
, - key
HiddenActivity
, - and value
closeOnError
.
- add an intent extra with the type
When testing intent injections, you’ll often need to specify com.kira.malware.activities.HiddenActivity as the target intent
class name, and scope the file or SQLite content provider intent extra to the same target intent
, as shown above.
Figure 3 - Pending Intent
Figure 4 - Fuzzing
Figure 5 - Intent Injection
Tip #1: Listen for a broadcast intent from another app.
Figure 6 - Broadcast Monitor
Tip #1: Initiate a deep link callback from a website to hijack the flow of another app.
Tip #2: Create further exploitation steps inside the source code using OkHttp, intents, and/or other components, then rebuild the APK.
Figure 7 - Web
Tip #1: To hijack a task of another app, modify the task affinity in this app's AndroidManifest.xml
under MainActivity, then rebuild the APK.
Figure 8 - Taskjacking
Tip #1: Test if another app can detect an overlay.
Tip #2: Detect an overlay by checking MotionEvent.FLAG_WINDOW_IS_OBSCUREDand
MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED flags - this solution works only on older Android versions.
Read more about tapjacking and how to protect from it here.
Figure 9 - Tapjacking
Tip #1: Extract sensitive information from another app's UI by abusing the accessibility service.
Figure 10 - Accessibility Service
Tip #1: Dump the clipboard and look for sensitive information.
Figure 11 - Miscellaneous
Tip #1: Save and restore the UI state at any time.
Figure 12 - Saving