Advanced levelPremiumbounty: $2500

Android XSS — exported Activity via ContentActivity (POE/Quora real report)

Walkthrough of Android XSS exploitable via an exported Activity intent in POE: how a filter-less ContentActivity leaks the WebView to attacker-controlled sites.

Gorka El BochiMay 11, 202613 min

Quick answer

On Android, an Activity marked exported="true" can be invoked by any installed app via an Intent — with no permissions. If that Activity accepts an html parameter and loads it directly into a WebView with the main domain's context (www.quora.com), you have stored XSS on mobile + access to the native JSBridge + escalation to RCE on Android ≤4.2. Quora paid $2,500 for this in 2016 and the pattern is still valid in modern Android apps (banking, social, productivity). 5 minutes with adb + Drozer reveal whether your target is vulnerable.


1. Refresher: how Android Intents work

Android has 4 component types: Activities, Services, BroadcastReceivers, ContentProviders. Any of them can have android:exported="true" in the AndroidManifest.xml.

xml
<activity
    android:name=".ContentActivity"
    android:exported="true">    <!-- ❌ accesible desde cualquier app -->
</activity>

When exported=true:

  • Any installed app can invoke it with an Intent.
  • It requires no special permissions (unless declared with <permission>).
  • The Intent extras are 100% attacker-controlled.

Why exported=true is sometimes set

  • Deep links (https://target.com/x → opens Activity X).
  • Integrations with other apps (share intent, file picker).
  • Custom URL schemes (myapp://).
  • On Android 12+ it's mandatory to explicitly declare exported=true/false — many devs set it true "for security" without understanding it's the opposite.

2. The real case — Quora Android (2016, $2,500)

Affected activities

xml
<activity android:name="com.quora.android.ContentActivity" android:exported="true"/>
<activity android:name="com.quora.android.ModalContentActivity" android:exported="true"/>
<activity android:name="com.quora.android.ActionBarContentActivity" android:exported="true"/>

All three accepted two Intent extras:

ExtraMeaning
urlReference URL (not validated)
htmlHTML content loaded directly into the WebView

The WebView was loaded with the context of www.quora.com — that is, any injected JS ran with that origin and with access to the native QuoraAndroid JSBridge.

Base payload via ADB

bash
adb shell am start \
  -n com.quora.android/com.quora.android.ActionBarContentActivity \
  -e url 'http://test/test' \
  -e html 'XSS<script>alert(document.domain)</script>'

Result: an alert with www.quora.com → XSS in Quora's authenticated context.


Keep reading the full chain

The remaining part includes the step-by-step PoC, exploitation code and the full chain that led to impact. Available to subscribers.

Free · no account

The checklist I run on every new target

47 checks ordered by cost: first what can get you in trouble, then the cheap stuff, and finally the expensive stuff — which is where the big bounties are. I'll send it to your inbox right now.

Unsubscribe in one click, from any email.

Practice this in a lab

Mobile Android Xss

Solve

Keep learning · free account

Save your progress, unlock advanced payloads and rank your flags.

Create account

Related articles

2,482

hunters training

62

labs from real hacks

1,629

completions

$14,790

paid out for these bugs

11 flags captured this week·Real hacks from HackerOne · YesWeHack · Bugcrowd·No commitment·Free Academy