🔗 Part 14: Deep Link & URI Hijacking in Flutter — How Malicious Apps Spoof or Intercept…

🔗 Part 14: Deep Link & URI Hijacking in Flutter — How Malicious Apps Spoof or Intercept…

FlutterPulse

This article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!🚀

Flutter apps commonly use deep links and custom URI schemes to:

đź”™ Check Previous Part [SSL Pinning Bypass in Flutter]

  • Authenticate via OAuth
  • Resume in-app navigation from emails or SMS
  • Handle app-to-app communication

However…

Without proper protection, malicious apps can hijack or spoof your deep links — enabling phishing, unauthorized actions, and even impersonation of your app.

This article breaks down how deep link & intent hijacking works in Flutter, real-world exploit techniques, and best practices to protect your app.

🔍 What's the Problem?

Flutter uses both:

  • URI schemes (myapp://callback)
  • App links / universal links (https://myapp.com/open?...)

These are mapped to activities (AndroidManifest.xml) or associated domains (Apple Universal Links / Android App Links).

But if:

  • The intent filter is too broad
  • You don't check the caller or referrer
  • Another app registers the same scheme before yours

…then another app can intercept, spoof, or launch your deep link flow maliciously.

🕵️‍♂️ Real-World Exploit Scenarios

đź’Ł Exploit 1: Custom Scheme Hijacking

Your app uses:

myapp://auth?token=XYZ

An attacker app registers the same intent in its AndroidManifest.xml:

<intent-filter>
<data android:scheme="myapp" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>

Result: When a user clicks a login link, attacker's app is launched, not yours.

đź’Ł Exploit 2: Intent Spoofing with adb

Attacker uses:

adb shell am start -W -a android.intent.action.VIEW -d "myapp://payment?amount=9999"

If your app does not validate origin or sanitize input, it might process payment or trigger unintended actions.

If your WebView opens a deep link that triggers native navigation, and you don't check source or content, a malicious site could:

window.location.href = "myapp://transfer?to=attacker&amount=1000";

The WebView → native → Flutter stack blindly processes this action.

đź’Ł Exploit 4: Multiple Apps with Same Scheme

If another app is installed first with the same scheme (myapp://), it may:

  • Receive the deep link meant for your app
  • Capture tokens, UIDs, or user inputs

📉 Real-World Impact

Risk Level: HIGH

🛡️ How to Fix It

These rely on verified domain association — not just schemes.

This prevents other apps from intercepting your links.

âś… Fix 2: Whitelist Specific Domains and Schemes

Avoid android:scheme="*" or open wildcards.

Instead:

<data android:scheme="myapp" android:host="auth" />

In Flutter, ensure your uni_links or app_links logic only responds to your exact URL patterns.

Example in Flutter:

void handleUri(Uri uri) {
final host = uri.host;
if (host != "auth" || !uri.queryParameters.containsKey('token')) {
return; // Reject spoofed/malformed URI
}
final token = uri.queryParameters['token'];
// Process only after validation
}

Validate:

  • URL format
  • Query parameters
  • Origin/referrer (if possible)
  • Content authenticity (JWTs, signed tokens)

Never allow deep link-triggered actions (payments, transfers, deletions) without a session check:

if (currentUser == null) {
// Don't process deep link
return;
}

âś… Fix 5: Avoid Sensitive Tokens in URI

Avoid links like:

myapp://auth?token=XYZ

Instead, use a short-lived code:

myapp://auth?code=123456

Then resolve token securely via backend.

Track:

  • Frequency of deep link openings
  • Originating apps (when available)
  • Repeated unusual parameters

Helps in detecting abuse or automation.

❌ Anti-Patterns to Avoid

âś… Developer Checklist

  • Prefer App/Universal Links over custom schemes
  • Validate deep link URL structure and parameters
  • Require user authentication before processing sensitive links
  • Avoid placing tokens or secrets in links
  • Whitelist host + scheme + path in routing logic
  • Reject untrusted or malformed URIs
  • Monitor deep link usage and log anomalies

đź‘€ Up Next

🚨 Part 15: Runtime Code Injection via Frida in Flutter Plugins — How Attackers Modify Native Behavior at Runtime

Thank you for reading this article

If I missed something or made an error, please let me know in the comments. I'm always eager to learn and improve.

Give a clap 👏 if you found this article helpful.

Report Page