Skip to content

Deeplinks and IPC

Mobile apps aren’t islands: they communicate with other apps and with the system through IPC (Inter-Process Communication) and deeplinks (links that open the app on a specific screen). If those entry points don’t validate who invokes them or the input they receive, they become an attack surface: another app (or a web page) can invoke internal functions, pass malicious data, or bypass UI controls.

# Android
Custom scheme: targetapp://screen?param=value (any app can invoke it)
App Links: https://target.com/... (domain-verified, safer)
# iOS
URL Schemes: targetapp://... (like a custom scheme, unverified)
Universal Links: https://target.com/... (domain-verified)

Custom schemes (targetapp://) are not verified: any app or web can invoke them, so whatever the app does with them must be validated.

# Android: from the decompiled manifest
# look for <intent-filter> with <data android:scheme="..."> and android:host
apktool d app.apk ; grep -A5 'intent-filter' AndroidManifest.xml
# iOS: from the Info.plist
plutil -p Info.plist | grep -A5 CFBundleURLSchemes
# Android: invoke a deeplink
adb shell am start -W -a android.intent.action.VIEW -d "targetapp://admin?debug=1" com.target
# iOS: with the simulator or Frida
# open the URL and observe which screen/action it leads to and what parameters it accepts
# unauthorized access to internal screens/functions
targetapp://admin or targetapp://transfer?to=attacker&amount=1000 (bypass UI/checks)
# injection via deeplink parameters
# -> XSS if the parameter reaches a WebView
# -> SQLi / path traversal if it reaches a query/file
# -> open redirect / controlled URL load in a WebView
# data theft: a deeplink that makes the app send data to a controlled destination
# deeplinks that start sensitive flows without re-authentication

Beyond deeplinks, exported components are IPC:

# Activities, Services, Broadcast Receivers, Content Providers with exported=true
adb shell am start -n com.target/.SecretActivity # Activity
adb shell am startservice -n com.target/.AdminService # Service
adb shell am broadcast -a com.target.ACTION_X # Broadcast
adb shell content query --uri content://com.target.provider/data # Content Provider
# drozer automates the analysis of this whole surface
drozer console connect ; run app.package.attacksurface com.target

An exported Content Provider without permissions can leak data or be vulnerable to SQLi/path traversal; a Receiver can trigger logic with fake intents.

# URL schemes (above), app extensions, shared app groups
# general pasteboard (data shared between apps)
# poorly validated Universal Links
  • Validate the input of deeplinks/intents (parameters, destinations) like any untrusted input.
  • Prefer App Links/Universal Links (domain-verified) over custom schemes.
  • Minimize exported components; protect the needed ones with permissions; exported=false by default.
  • Don’t execute sensitive actions from a deeplink without re-authentication/confirmation.
  • Secure WebViews if a parameter reaches them (no unnecessary JS, don’t load controlled URLs).
  • Validate the origin (getCallingPackage/referrer) when who invokes matters.
  • Enumerate deeplinks (manifest / Info.plist)
  • Invoke deeplinks and see which screens/actions they lead to
  • Unauthorized access to internal functions via deeplink
  • Injection via parameters (XSS in WebView, SQLi, traversal)
  • Android exported components (am/content, drozer)
  • Content Providers: SQLi/path traversal/data leak
  • Sensitive flows without re-authentication
  • iOS: URL schemes, Universal Links, pasteboard