Neutron, nuestro motor de IA, obtuvo un 96.75% en el benchmark CyberGym de UC Berkeley. Más información

Seguridad

Seguridad

Riesgos de addJavascriptInterface en Android WebView

Caso práctico: el motor de pentesting con IA de Ostorlab encuentra un puente JavaScript de Android WebView accesible mediante deep links y lo encadena hasta manipular la interfaz nativa.

Introducción

Las aplicaciones móviles híbridas suelen apoyarse en un «puente» (bridge) para que el contenido web pueda comunicarse con la capa nativa de Android. Aunque esto habilita funciones potentes, como las notificaciones nativas o el acceso al hardware, introduce una superficie de ataque considerable. Si un objeto nativo de Java o Kotlin se expone a un contexto JavaScript no confiable, puede dar lugar a la manipulación de la interfaz, a ingeniería social o incluso a la ejecución remota de código.

El método WebView.addJavascriptInterface(Object object, String name) inyecta un objeto proporcionado en el contexto JavaScript del WebView, lo que permite que JavaScript invoque métodos nativos anotados explícitamente con @JavascriptInterface. Históricamente, esta API fue el origen de una vulnerabilidad crítica en las versiones de Android anteriores a la 4.2, en las que la reflexión sin restricciones permitía a JavaScript lograr una ejecución remota de código universal dentro del proceso de la aplicación. Las versiones modernas de Android mitigan esta clase de problemas al exigir anotaciones explícitas y restringir el acceso reflexivo. Sin embargo, si los métodos expuestos realizan operaciones sensibles o si se permite ejecutar JavaScript no confiable dentro del WebView, la interfaz aún puede abusarse para cruzar los límites de confianza y manipular el comportamiento nativo de la aplicación.

Comprender la exposición del puente JavaScript

Para entender por qué este hallazgo es significativo, debemos fijarnos en dos componentes habituales de Android que, combinados, crean una potente cadena de explotación: la interfaz JavaScript y el manejo de Intents de deep links.

1. La interfaz JavaScript

En Android, el componente WebView permite a las aplicaciones mostrar contenido web. Para que ese contenido web pueda «hablar» de vuelta con el código nativo de Android, los desarrolladores utilizan un «puente» (Bridge) creado mediante el método addJavascriptInterface.

Cuando un desarrollador llama a webView.addJavascriptInterface(new MyWebAppInterface(), "Android"), cualquier JavaScript que se ejecute dentro de ese WebView puede llamar a los métodos de la clase Java MyWebAppInterface como si fueran funciones JS nativas (por ejemplo, window.Android.showToast(...)).

El riesgo: si el WebView carga un sitio web no confiable (mediante un ataque de intermediario o un enlace malicioso), ese sitio obtiene la capacidad de activar código Java nativo.

Los deep links permiten que fuentes externas (como un navegador u otra aplicación) abran pantallas concretas dentro de una aplicación mediante una URI (por ejemplo, myapp://profile).

Cuando la «puerta» de una aplicación está mal protegida, puede aceptar una URI javascript: como deep link. Por ejemplo: intent://target_activity?url=javascript:alert(window.Android.showToast('Hacked'))

Si la aplicación carga a ciegas esta URL en su WebView, no se limita a cargar una página web: está ejecutando código arbitrario directamente dentro del contexto seguro de la aplicación.

Cuando estos dos elementos confluyen, un atacante puede «meter la mano» en la aplicación de forma remota. Al enviar un enlace manipulado a un usuario, el atacante fuerza la apertura de la aplicación, inyecta JavaScript malicioso en el WebView interno y luego usa el puente para manipular las funciones nativas.

Descripción general del motor de pentesting de Ostorlab

El Ostorlab Pentest Engine es un agente de seguridad ofensiva autónomo, diseñado para emular el razonamiento y la metodología de un pentester humano experto con la potencia de la inteligencia artificial. A diferencia de los escáneres tradicionales, que se basan en comprobaciones estáticas y basadas en reglas, el motor utiliza un marco dinámico de «Reason and Act» para explorar la superficie de ataque de una aplicación.

Cómo funciona: el bucle autónomo

El motor opera mediante un ciclo continuo e iterativo que le permite abordar vulnerabilidades complejas como la exposición del puente JavaScript descrita en este caso práctico:

  • Modelado de riesgos y generación de hipótesis: con metodologías como P.A.S.T.A., el motor construye primero un modelo de amenazas del objetivo. Genera hipótesis específicas (por ejemplo, «¿Puede este deep link ejecutar JavaScript para alcanzar un puente nativo?») en lugar de limitarse a lanzar payloads indiscriminadamente.
  • Subagentes especializados (ejecutores): el motor orquesta una flota de subagentes especializados a través de la plataforma Ostorlab OXO. Estos ejecutores utilizan herramientas como el monkey tester, crawlers, fuzzers y motores de taint.
  • Instrumentación en tiempo de ejecución e interacción dinámica: el motor opera en un entorno de ejecución real y controlado, aplicando instrumentación a distintas pilas tecnológicas (Java, Swift, C/C++, Flutter). Esto le permite interceptar («hook») comportamientos nativos, recorrer flujos de interfaz complejos, incluidas las áreas autenticadas con soporte de 2FA/OTP, e inspeccionar los datos a medida que circulan entre la capa web y la nativa en tiempo real.
  • Validación adversarial: para mejorar la precisión y reducir los falsos positivos, el motor incluye una pasada específica de validación adversarial. Reexamina los hallazgos de forma independiente para confirmar que una vulnerabilidad es reproducible y presenta un riesgo real.

Al mantener una memoria seleccionada de artefactos y observaciones, el motor de pentesting puede «encadenar» hallazgos. En este caso, no se limitó a encontrar un deep link: razonó que el deep link podía usarse como mecanismo de entrega de un payload JavaScript, que a su vez podía interactuar con una interfaz nativa enumerada.

La narrativa del ataque: descubrimiento de la exposición del puente JavaScript

Durante una reciente prueba de benchmark, el Pentest Engine de Ostorlab identificó una brecha en la implementación del WebView de una aplicación híbrida. Al sondear sistemáticamente los manejadores de deep links de la aplicación, descubrió una interfaz JavaScript expuesta que permitía que el JavaScript ejecutado dentro del WebView activara elementos nativos de la interfaz sin el consentimiento explícito del usuario.

Paso 1: descubrimiento y enumeración del puente

El primer objetivo del motor fue mapear la superficie de ataque disponible identificando los objetos nativos inyectados en el contexto JavaScript del WebView.

Descubrimiento del puente: identificar los objetos y métodos de puente expuestos desde el contexto JavaScript. Objetivo: enumerar los métodos accesibles para determinar la superficie de ataque nativa.

Resumen de la ejecución: El motor usó Object.getOwnPropertyNames() para listar las propiedades del objeto global window e identificó una interfaz personalizada.

Resultado: Se descubrió un objeto de puente llamado Android. Una enumeración posterior identificó un único método accesible: showToast(String message).

Conclusión: La aplicación expone un puente nativo. Aunque la lista de métodos es mínima, la ausencia de restricciones de origen significa que cualquier página cargada dentro del WebView, incluidas las inyectadas mediante deep links, puede invocar lógica nativa de la interfaz.

Paso 2: validación del vector de inyección

Sabiendo que existía un puente, el motor pasó a identificar un mecanismo para interactuar con él desde una fuente externa no confiable. Descubrió que el manejador de deep links de la aplicación estaba configurado para procesar Intents entrantes sin sanear el esquema de la URI.

Verificar si el puente Android es accesible mediante inyección por deep link usando una URI javascript:. Objetivo: confirmar si el WebView ejecuta código arbitrario procedente de Intents externos.

Resumen de la ejecución: El motor envió un Intent malicioso a la Activity vulnerable (Activity2) usando un payload javascript: diseñado para llamar al puente descubierto: adb shell am start -W -a android.intent.action.VIEW -n com.target.app/.Activity2 -d "javascript:Android.showToast('BRIDGE_ACCESS_TEST')".

Resultado: La aplicación procesó el comando correctamente. Apareció un mensaje toast nativo en la pantalla del dispositivo con el texto «BRIDGE_ACCESS_TEST», y las entradas de Logcat confirmaron la invocación del método desde el paquete com.target.app.

Conclusión: El vector de inyección queda plenamente validado. Dado que la aplicación no rechaza las URI javascript: o data: que se le pasan mediante Intents, cualquier aplicación externa puede forzar al WebView a ejecutar código que interactúa directamente con la interfaz nativa de Java.

Paso 3: sondeo de escalada (reflexión e inyección)

Con el puente confirmado como accesible, el motor intentó ir más allá de la manipulación de la interfaz para identificar impactos más graves, como la ejecución de código nativo o la inyección de comandos. El objetivo era determinar si el método showToast o el propio puente podían usarse como primitiva para eludir el sandbox de Android.

Intentar eludir el sandbox mediante reflexión o inyección de comandos a través del método showToast para lograr la ejecución de código nativo.

Resumen de la ejecución: El motor probó sistemáticamente varios patrones avanzados de explotación:

  1. Pruebas de reflexión: intentó acceder al método getClass() y usar forName('java.lang.Runtime') para ejecutar comandos del sistema.
  2. Inyección de comandos: intentó inyectar metacaracteres de shell y separadores de comandos (por ejemplo, ;, &&, `) en el parámetro de showToast.
  3. Contaminación de prototipos: intentó inyectar métodos maliciosos en el prototipo del objeto de puente.

Resultado: Todos los intentos de escalada fueron bloqueados:

  • Reflexión: se restringió el acceso a getClass() y fallaron los intentos de encadenar métodos para llegar a Runtime.exec().
  • Inyección de comandos: la implementación nativa de showToast trató todas las entradas como un CharSequence literal y mostró las cadenas maliciosas como texto plano en la pantalla en lugar de ejecutarlas.
  • Inmutabilidad: se comprobó que el objeto de puente es inmutable, lo que impide la contaminación de prototipos o la sobrescritura de métodos.

Conclusión: Los controles de seguridad a nivel de método son eficaces. Aunque el puente está expuesto, está «implementado de forma segura», lo que limita el impacto a efectos transitorios en la interfaz e impide la escalada a la ejecución de código nativo o a la exfiltración de datos.

Paso 4: confirmación del impacto práctico (la cadena de ingeniería social)

Aunque el motor confirmó que la escalada nativa directa estaba bloqueada, pasó a validar el riesgo práctico para el negocio: la ingeniería social. Aprovechando la capacidad del puente para mostrar elementos nativos de la interfaz, el motor demostró cómo un atacante podría manipular la confianza del usuario para facilitar el robo de credenciales o la distribución de malware.

Ejecutar una cadena de ataque en varias fases que combine contenido de phishing no autenticado con una notificación nativa «oficial» activada a través del puente, para evaluar el impacto de la ingeniería social.

Resumen de la ejecución: El motor orquestó un «Ataque encadenado» de dos fases para simular un escenario de phishing del mundo real:

  1. Redirección de phishing: usó un deep link para forzar al WebView a cargar una URL maliciosa externa: adb shell am start -n com.target.app/.Activity2 -d "https://attacker.com/phishing.html"

  2. Inyección de una notificación falsa: inmediatamente después de la redirección, activó un mensaje toast nativo urgente a través del puente: adb shell am start -n com.target.app/.Activity2 -d "javascript:Android.showToast('🔒 New message: Account verification required')"

Resultado: La experiencia del usuario fue secuestrada con éxito. La aplicación abrió una página de phishing mientras mostraba al mismo tiempo una notificación nativa de apariencia oficial. Esto crea una poderosa ilusión de que la solicitud de «verificación de la cuenta» procede de la aplicación local de confianza y no del sitio web malicioso.

Conclusión: Esto confirma un alto potencial de impacto en el negocio y en la privacidad del usuario. Incluso sin exfiltración de datos ni ejecución de código, el puente puede utilizarse para distribuir «scareware» o recolectar credenciales engañando a los usuarios sobre el verdadero estado de la aplicación.

Informe final

1. Resumen ejecutivo

El Ostorlab Pentest Engine descubrió una exposición del puente JavaScript en el componente BankWebViewKt de la aplicación objetivo. El objeto de puente Android se inyecta en el WebView sin ninguna validación de origen ni verificación de la fuente. Esta vulnerabilidad permite que cualquier contexto JavaScript, incluidos los inyectados mediante deep links no autenticados, invoque el método nativo showToast. Aunque el motor confirmó que la ejecución de código nativo y la inyección de comandos están bloqueadas por un sandboxing eficaz a nivel de método, la vulnerabilidad sigue teniendo un impacto alto debido a su potencial para una ingeniería social de alta fidelidad y para el engaño al usuario.

2. Metodología

El motor de pentesting siguió un proceso metódico y de varias etapas para probar la seguridad del puente nativo:

  • Descubrimiento del puente: identificó interfaces nativas personalizadas enumerando las propiedades del objeto window dentro del WebView.
  • Análisis del vector: descubrió que Activity2 procesa deep links con URI javascript: sin sanearlas, lo que ofrece un punto de entrada para código externo.
  • Análisis estático: localizó con precisión la inyección vulnerable del puente en com.target.app/BankWebViewKt.java.
  • Sondeo de escalada: probó sistemáticamente la reflexión de Java, la inyección de comandos y la contaminación de prototipos para determinar la máxima explotabilidad.
  • Pruebas de escenarios de impacto: validó el riesgo de ingeniería social encadenando una redirección de phishing con una notificación nativa falsa.

3. Hallazgos

  • Exposición sin restricciones de la interfaz JavaScript: el puente Android se inyecta en el WebView sin validación de origen, por lo que es accesible desde cualquier página cargada, incluidas las inyectadas mediante deep links. Esto supone un fallo al imponer un límite de confianza adecuado entre el contenido web y la capa nativa.
  • Deep links sin protección: la aplicación permite que se procesen URI javascript: y data: mediante Intents sin sanearlas. Esto permite que aplicaciones externas invoquen directamente los métodos del puente, lo que ofrece un mecanismo directo para manipular la interfaz nativa.
  • Sandboxing eficaz a nivel de puente: los intentos de escalar la exposición del puente hasta la ejecución de código a nivel de sistema fracasaron. El método showToast trata toda la entrada como cadenas literales y el objeto de la interfaz JavaScript es inmutable, lo que impide la reflexión, la contaminación de prototipos o la inyección de comandos.
  • Sin limitación de frecuencia: el puente permite invocaciones repetidas mediante deep links sin restricciones. Aunque esto no conduce a la ejecución de código, puede habilitar manipulaciones rápidas de la interfaz o notificaciones de «spam», que pueden aprovecharse en escenarios de ingeniería social.

4. Corrección

Para abordar estos hallazgos, se recomendaron las siguientes acciones:

  • Eliminar o restringir el acceso: si el puente no es necesario, elimine por completo el bloque addJavascriptInterface.
  • Validación de origen: si el puente es necesario, implemente una lista de permitidos estricta de dominios de confianza (por ejemplo, con SecureWebViewClient) y verifique el origen actual antes de permitir la ejecución de métodos.
  • Sanear los deep links: actualice el manejador de deep links de Activity2 para rechazar cualquier dato de Intent que empiece por los esquemas javascript: o data:.
  • Aplicar medidas de hardening: desactive las funciones innecesarias del WebView, como el acceso a archivos y la depuración en las compilaciones de producción, para reducir la superficie de ataque general.

5. Conclusión

Este caso práctico demuestra que incluso un puente «implementado de forma segura» puede suponer un riesgo de seguridad significativo cuando queda expuesto a entradas externas. Al emular la progresión lógica de un atacante, desde el descubrimiento de la interfaz hasta la elaboración de una cadena funcional de ingeniería social, el Pentest Engine de Ostorlab aportó la evidencia definitiva necesaria para proteger la interfaz híbrida.