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 with 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 encoding and decoding section to support transforming text into formats compatible with
Bundle.putByteArray()
and others, - add an option to download and import saved UI states,
- add an option to bind to a service,
- add a capability to pass overlay button clicks to an underlying view,
- hide soft keyboard when user taps outside a text 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 v3.1
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.
Tip #11: HiddenActivity
allows you to verify the intent and its extras before dispatching it.
The following applies only to the proxy intent
extras:
- If the value is a string equal to
</target-pending-intent>
:- 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
</target-intent>
:- 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
</target-intent-uri>
:- 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
</target-intent-uri-unsafe>
:- 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
</file-provider>
.
- 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
</sqlite-provider>
.
- add an intent extra with the type
- To auto-close the callback activity on success:
- add an intent extra with the type
string
, - key
HiddenActivityClose
, - and value
</close-on-success>
.
- add an intent extra with the type
- To auto-close the callback activity on error:
- add an intent extra with the type
string
, - key
HiddenActivityClose
, - and value
</close-on-error>
.
- 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: Leverage existing web browser sessions to hijack the authenticated flow of another app.
Tip #3: 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.
Read more about the vulnerability and possible protection here.
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.
Read more about the possible protection here;
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