Respuesta rápida
En Android, una Activity marcada exported="true" puede ser invocada por cualquier app instalada vía Intent — sin permisos. Si esa Activity acepta un parámetro html y lo carga directo en un WebView con contexto del dominio principal (www.quora.com), tienes stored XSS en mobile + acceso al JSBridge nativo + escalación a RCE en Android ≤4.2. Quora pagó $2,500 por esto en 2016 y el patrón sigue vigente en apps Android modernas (banking, social, productivity). 5 minutos con adb + Drozer descubren si tu target es vulnerable.
1. Refresher: cómo funciona Android Intents
Android tiene 4 tipos de components: Activities, Services, BroadcastReceivers, ContentProviders. Cualquiera puede tener android:exported="true" en el AndroidManifest.xml.
<activity
android:name=".ContentActivity"
android:exported="true"> <!-- ❌ accesible desde cualquier app -->
</activity>
Cuando exported=true:
- Cualquier app instalada puede invocarla con un Intent.
- No requiere permisos especiales (a menos que se declaren con
<permission>). - Los
Intent extrasson atacante-controlados al 100%.
Por qué a veces se marca exported=true
- Deep links (
https://target.com/x→ abre Activity X). - Integraciones con otras apps (share intent, file picker).
- Custom URL schemes (
myapp://). - En Android 12+ es obligatorio declarar exported=true/false explícitamente — muchos devs lo ponen true "por seguridad" sin entender que es lo contrario.
2. El caso real — Quora Android (2016, $2,500)
Activities afectadas
<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"/>
Las tres aceptaban dos Intent extras:
| Extra | Significado |
|---|---|
url | URL de referencia (no validada) |
html | Contenido HTML que se carga directo en el WebView |
El WebView se cargaba con el contexto de www.quora.com — es decir, cualquier JS inyectado corría con ese origen y con acceso al JSBridge nativo QuoraAndroid.
Payload base via ADB
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>'
Resultado: alert con www.quora.com → XSS en contexto autenticado de Quora.
Sigue leyendo el chain completo
La parte que falta incluye el PoC paso a paso, código de explotación y la cadena completa que llevó al impacto. Disponible para suscriptores.
La checklist que repaso en cada objetivo nuevo
47 comprobaciones ordenadas por coste: primero lo que te puede meter en un lío, luego lo barato, y al final lo caro — que es donde están los bounties grandes. Te la mando al correo ahora mismo.
Te das de baja en un clic, desde cualquier correo.
Practica esto en un lab
Mobile Android Xss
Sigue aprendiendo · cuenta gratis
Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.
Artículos relacionados
Stored XSS en nombres de plantilla — del campo más aburrido al domain takeover
Un campo de título en una plantilla, sin sanitizar, en una sesión con permisos sobre dominios. Bounty real de €1.200. Cómo encontrar XSS donde nadie mira.
DOM XSS — gadgets, postMessage handlers y CVE-2025-59840
DOM XSS no es solo innerHTML. Sources/sinks, gadget chains via toString(), postMessage handlers sin origin check, hash-based routing rotos.
postMessage — vulnerabilidades comunes: origin bypass, XSS sink, IDOR cross-window
Cómo identificar y explotar vulnerabilidades en window.postMessage(): listeners sin validación de origin, payloads JSON inseguros que llegan a DOM XSS, IDOR cross-origin.
