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.
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.