Βασικά Στοιχεία Εφαρμογών Android

Reading time: 24 minutes

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

Μοντέλο Ασφαλείας Android

Υπάρχουν δύο επίπεδα:

  • Το OS, το οποίο κρατά τις εγκατεστημένες εφαρμογές απομονωμένες η μία από την άλλη.
  • Η εφαρμογή αυτή καθαυτή, η οποία επιτρέπει στους προγραμματιστές να εκθέτουν ορισμένες λειτουργίες και ρυθμίζει τις δυνατότητες της εφαρμογής.

Διαχωρισμός UID

Κάθε εφαρμογή ανατίθεται σε μια συγκεκριμένη Ταυτότητα Χρήστη (User ID). Αυτό γίνεται κατά την εγκατάσταση της εφαρμογής ώστε η εφαρμογή να μπορεί να αλληλεπιδρά μόνο με αρχεία που ανήκουν στην Ταυτότητα Χρήστη της ή με κοινά αρχεία. Επομένως, μόνο η ίδια η εφαρμογή, ορισμένα στοιχεία του OS και ο χρήστης root μπορούν να έχουν πρόσβαση στα δεδομένα της εφαρμογής.

Κοινή Χρήση UID

Δύο εφαρμογές μπορούν να ρυθμιστούν να χρησιμοποιούν την ίδια UID. Αυτό μπορεί να είναι χρήσιμο για την κοινή χρήση πληροφοριών, αλλά αν μία από αυτές παραβιαστεί, τα δεδομένα και των δύο εφαρμογών θα παραβιαστούν. Γι' αυτόν τον λόγο αυτή η συμπεριφορά αποθαρρύνεται.
Για να μοιραστούν την ίδια UID, οι εφαρμογές πρέπει να ορίσουν την ίδια τιμή android:sharedUserId στα μανιφέστα τους.

Sandbox

Η Sandbox Εφαρμογών Android επιτρέπει να εκτελούνται κάθε εφαρμογή ως ξεχωριστή διαδικασία υπό μια ξεχωριστή Ταυτότητα Χρήστη. Κάθε διαδικασία έχει τη δική της εικονική μηχανή, έτσι ο κώδικας μιας εφαρμογής εκτελείται σε απομόνωση από άλλες εφαρμογές.
Από το Android 5.0(L) επιβάλλεται το SELinux. Βασικά, το SELinux αρνείται όλες τις αλληλεπιδράσεις διαδικασιών και στη συνέχεια δημιουργεί πολιτικές για να επιτρέπει μόνο τις αναμενόμενες αλληλεπιδράσεις μεταξύ τους.

Άδειες

Όταν εγκαθιστάτε μια εφαρμογή και ζητά άδειες, η εφαρμογή ζητά τις άδειες που έχουν ρυθμιστεί στα στοιχεία uses-permission στο αρχείο AndroidManifest.xml. Το στοιχείο uses-permission υποδεικνύει το όνομα της ζητούμενης άδειας μέσα στο attribute name. Έχει επίσης το maxSdkVersion attribute που σταματά να ζητά άδειες σε εκδόσεις υψηλότερες από αυτήν που έχει καθοριστεί.
Σημειώστε ότι οι εφαρμογές Android δεν χρειάζεται να ζητούν όλες τις άδειες στην αρχή, μπορούν επίσης να ζητούν άδειες δυναμικά αλλά όλες οι άδειες πρέπει να είναι δηλωμένες στο μανιφέστο.

Όταν μια εφαρμογή εκθέτει λειτουργικότητα μπορεί να περιορίσει την πρόσβαση μόνο σε εφαρμογές που έχουν μια καθορισμένη άδεια.
Ένα στοιχείο άδειας έχει τρία attributes:

  • Το όνομα της άδειας
  • Το attribute permission-group, το οποίο επιτρέπει την ομαδοποίηση σχετικών αδειών.
  • Το protection-level που υποδεικνύει πώς χορηγούνται οι άδειες. Υπάρχουν τέσσερις τύποι:
  • Normal: Χρησιμοποιείται όταν δεν υπάρχουν γνωστές απειλές για την εφαρμογή. Ο χρήστης δεν απαιτείται να την εγκρίνει.
  • Dangerous: Υποδεικνύει ότι η άδεια παρέχει στην αιτούσα εφαρμογή κάποια υψηλή πρόσβαση. Οι χρήστες ζητούνται να τις εγκρίνουν.
  • Signature: Μόνο εφαρμογές που υπογράφονται από το ίδιο πιστοποιητικό με αυτό που εξάγει το στοιχείο μπορούν να λάβουν άδεια. Αυτός είναι ο ισχυρότερος τύπος προστασίας.
  • SignatureOrSystem: Μόνο **εφαρμογές που υπογράφονται από το ίδιο πιστοποιητικό με αυτό που εξάγει το στοιχείο ή εφαρμογές που εκτελούνται με πρόσβαση σε επίπεδο συστήματος μπορούν να λάβουν άδειες.

Προεγκατεστημένες Εφαρμογές

Αυτές οι εφαρμογές βρίσκονται γενικά στους καταλόγους /system/app ή /system/priv-app και μερικές από αυτές είναι βελτιστοποιημένες (μπορεί να μην βρείτε καν το αρχείο classes.dex). Αυτές οι εφαρμογές αξίζουν να ελεγχθούν γιατί μερικές φορές εκτελούνται με πάρα πολλές άδειες (ως root).

  • Αυτές που αποστέλλονται με το AOSP (Android OpenSource Project) ROM
  • Προστέθηκαν από τον κατασκευαστή της συσκευής
  • Προστέθηκαν από τον πάροχο κινητής τηλεφωνίας (αν αγοράστηκαν από αυτούς)

Rooting

Για να αποκτήσετε πρόσβαση root σε μια φυσική συσκευή Android, γενικά χρειάζεται να εκμεταλλευτείτε 1 ή 2 ευπάθειες που συνήθως είναι συγκεκριμένες για τη συσκευή και την έκδοση.
Αφού η εκμετάλλευση έχει λειτουργήσει, συνήθως το δυαδικό su του Linux αντιγράφεται σε μια τοποθεσία που καθορίζεται στη μεταβλητή περιβάλλοντος PATH του χρήστη όπως /system/xbin.

Αφού το δυαδικό su έχει ρυθμιστεί, χρησιμοποιείται μια άλλη εφαρμογή Android για να αλληλεπιδράσει με το δυαδικό su και να επεξεργαστεί αιτήματα για πρόσβαση root όπως Superuser και SuperSU (διαθέσιμα στο Google Play store).

caution

Σημειώστε ότι η διαδικασία rooting είναι πολύ επικίνδυνη και μπορεί να προκαλέσει σοβαρή ζημιά στη συσκευή.

ROMs

Είναι δυνατόν να αντικαταστήσετε το OS εγκαθιστώντας ένα προσαρμοσμένο firmware. Κάνοντας αυτό, είναι δυνατό να επεκτείνετε τη χρησιμότητα μιας παλιάς συσκευής, να παρακάμψετε περιορισμούς λογισμικού ή να αποκτήσετε πρόσβαση στον τελευταίο κώδικα Android.
OmniROM και LineageOS είναι δύο από τα πιο δημοφιλή firmware που χρησιμοποιούνται.

Σημειώστε ότι δεν είναι πάντα απαραίτητο να κάνετε root τη συσκευή για να εγκαταστήσετε ένα προσαρμοσμένο firmware. Ορισμένοι κατασκευαστές επιτρέπουν την ξεκλείδωσή των bootloaders τους με καλά τεκμηριωμένο και ασφαλή τρόπο.

Επιπτώσεις

Αφού μια συσκευή είναι rooted, οποιαδήποτε εφαρμογή θα μπορούσε να ζητήσει πρόσβαση ως root. Αν μια κακόβουλη εφαρμογή το αποκτήσει, θα έχει πρόσβαση σχεδόν σε όλα και θα μπορεί να προκαλέσει ζημιά στο τηλέφωνο.

Θεμελιώδη Στοιχεία Εφαρμογών Android

  • Η μορφή των εφαρμογών Android αναφέρεται ως APK file format. Είναι ουσιαστικά ένα ZIP αρχείο (με την αλλαγή της επέκτασης αρχείου σε .zip, τα περιεχόμενα μπορούν να εξαχθούν και να προβληθούν).
  • Περιεχόμενα APK (Όχι εξαντλητικά)
  • AndroidManifest.xml
  • resources.arsc/strings.xml
  • resources.arsc: περιέχει προεγκατεστημένους πόρους, όπως δυαδικό XML.
  • res/xml/files_paths.xml
  • META-INF/
  • Εδώ βρίσκεται το Πιστοποιητικό!
  • classes.dex
  • Περιέχει Dalvik bytecode, που αντιπροσωπεύει τον μεταγλωττισμένο κώδικα Java (ή Kotlin) που εκτελεί η εφαρμογή από προεπιλογή.
  • lib/
  • Περιέχει εγγενείς βιβλιοθήκες, διαχωρισμένες κατά αρχιτεκτονική CPU σε υποκαταλόγους.
  • armeabi: κώδικας για επεξεργαστές ARM
  • armeabi-v7a: κώδικας για επεξεργαστές ARMv7 και ανώτερους
  • x86: κώδικας για επεξεργαστές X86
  • mips: κώδικας μόνο για επεξεργαστές MIPS
  • assets/
  • Αποθηκεύει διάφορα αρχεία που χρειάζεται η εφαρμογή, ενδεχομένως περιλαμβάνοντας επιπλέον εγγενείς βιβλιοθήκες ή αρχεία DEX, που μερικές φορές χρησιμοποιούνται από συγγραφείς κακόβουλου λογισμικού για να αποκρύψουν επιπλέον κώδικα.
  • res/
  • Περιέχει πόρους που δεν έχουν μεταγλωττιστεί σε resources.arsc.

Dalvik & Smali

Στην ανάπτυξη Android, χρησιμοποιείται Java ή Kotlin για τη δημιουργία εφαρμογών. Αντί να χρησιμοποιεί την JVM όπως στις επιτραπέζιες εφαρμογές, το Android μεταγλωττίζει αυτόν τον κώδικα σε Dalvik Executable (DEX) bytecode. Παλαιότερα, η εικονική μηχανή Dalvik χειριζόταν αυτόν τον bytecode, αλλά τώρα, το Android Runtime (ART) αναλαμβάνει σε νεότερες εκδόσεις Android.

Για την αντίστροφη μηχανική, το Smali γίνεται κρίσιμο. Είναι η αναγνώσιμη από άνθρωπο έκδοση του DEX bytecode, λειτουργώντας σαν γλώσσα assembly μεταφράζοντας τον πηγαίο κώδικα σε εντολές bytecode. Το Smali και το baksmali αναφέρονται στα εργαλεία συναρμολόγησης και αποσυναρμολόγησης σε αυτό το πλαίσιο.

Intents

Τα Intents είναι ο κύριος τρόπος με τον οποίο οι εφαρμογές Android επικοινωνούν μεταξύ των στοιχείων τους ή με άλλες εφαρμογές. Αυτά τα αντικείμενα μηνυμάτων μπορούν επίσης να μεταφέρουν δεδομένα μεταξύ εφαρμογών ή στοιχείων, παρόμοια με το πώς χρησιμοποιούνται τα GET/POST αιτήματα στις επικοινωνίες HTTP.

Έτσι, ένα Intent είναι βασικά ένα μήνυμα που μεταφέρεται μεταξύ στοιχείων. Τα Intents μπορούν να κατευθύνονται σε συγκεκριμένα στοιχεία ή εφαρμογές, ή μπορούν να σταλούν χωρίς συγκεκριμένο παραλήπτη.
Για να είμαστε απλοί, το Intent μπορεί να χρησιμοποιηθεί:

  • Για να ξεκινήσει μια Δραστηριότητα, συνήθως ανοίγοντας μια διεπαφή χρήστη για μια εφαρμογή
  • Ως ραδιοφωνικές εκπομπές για να ενημερώσουν το σύστημα και τις εφαρμογές για αλλαγές
  • Για να ξεκινήσει, να σταματήσει και να επικοινωνήσει με μια υπηρεσία στο παρασκήνιο
  • Για να αποκτήσει πρόσβαση σε δεδομένα μέσω ContentProviders
  • Ως callbacks για να χειριστεί γεγονότα

Αν είναι ευάλωτα, τα Intents μπορούν να χρησιμοποιηθούν για την εκτέλεση διαφόρων επιθέσεων.

Intent-Filter

Τα Intent Filters καθορίζουν πώς μια δραστηριότητα, υπηρεσία ή Broadcast Receiver μπορεί να αλληλεπιδράσει με διάφορους τύπους Intents. Βασικά, περιγράφουν τις δυνατότητες αυτών των στοιχείων, όπως ποιες ενέργειες μπορούν να εκτελούν ή τους τύπους ραδιοφωνικών εκπομπών που μπορούν να επεξεργαστούν. Ο κύριος χώρος για να δηλωθούν αυτά τα φίλτρα είναι μέσα στο AndroidManifest.xml αρχείο, αν και για τους Broadcast Receivers, η κωδικοποίησή τους είναι επίσης μια επιλογή.

Τα Intent Filters αποτελούνται από κατηγορίες, ενέργειες και φίλτρα δεδομένων, με τη δυνατότητα να περιλαμβάνουν επιπλέον μεταδεδομένα. Αυτή η ρύθμιση επιτρέπει στα στοιχεία να χειρίζονται συγκεκριμένα Intents που ταιριάζουν με τα δηλωμένα κριτήρια.

Ένας κρίσιμος τομέας των στοιχείων Android (δραστηριότητες/υπηρεσίες/παρόχοι περιεχομένου/δέκτες ραδιοφωνικών εκπομπών) είναι η ορατότητά τους ή η δημόσια κατάσταση. Ένα στοιχείο θεωρείται δημόσιο και μπορεί να αλληλεπιδράσει με άλλες εφαρμογές αν είναι exported με τιμή true ή αν έχει δηλωθεί ένα Intent Filter γι' αυτό στο μανιφέστο. Ωστόσο, υπάρχει τρόπος για τους προγραμματιστές να κρατήσουν αυτά τα στοιχεία ιδιωτικά, διασφαλίζοντας ότι δεν αλληλεπιδρούν με άλλες εφαρμογές κατά λάθος. Αυτό επιτυγχάνεται ρυθμίζοντας το exported attribute σε false στις δηλώσεις τους στο μανιφέστο.

Επιπλέον, οι προγραμματιστές έχουν τη δυνατότητα να ασφαλίσουν περαιτέρω την πρόσβαση σε αυτά τα στοιχεία απαιτώντας συγκεκριμένες άδειες. Το permission attribute μπορεί να ρυθμιστεί ώστε να επιβάλλει ότι μόνο οι εφαρμογές με την καθορισμένη άδεια μπορούν να έχουν πρόσβαση στο στοιχείο, προσθέτοντας ένα επιπλέον επίπεδο ασφάλειας και ελέγχου σχετικά με το ποιος μπορεί να αλληλεπιδράσει με αυτό.

java
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>

Implicit Intents

Intents δημιουργούνται προγραμματικά χρησιμοποιώντας έναν κατασκευαστή Intent:

java
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

Η Δράση της προηγουμένως δηλωμένης πρόθεσης είναι ACTION_SEND και το Επιπλέον είναι ένα mailto Uri (το Επιπλέον είναι οι επιπλέον πληροφορίες που αναμένει η πρόθεση).

Αυτή η πρόθεση θα πρέπει να δηλωθεί μέσα στο μανιφέστο όπως στο παρακάτω παράδειγμα:

xml
<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 πρέπει να ταιριάζει με την ενέργεια, δεδομένα και κατηγορία για να λάβει ένα μήνυμα.

Η διαδικασία "Επίλυσης Intent" καθορίζει ποια εφαρμογή θα λάβει κάθε μήνυμα. Αυτή η διαδικασία εξετάζει το χαρακτηριστικό προτεραιότητας, το οποίο μπορεί να οριστεί στην δήλωση intent-filter, και αυτό με την υψηλότερη προτεραιότητα θα επιλεγεί. Αυτή η προτεραιότητα μπορεί να οριστεί μεταξύ -1000 και 1000 και οι εφαρμογές μπορούν να χρησιμοποιήσουν την τιμή SYSTEM_HIGH_PRIORITY. Εάν προκύψει μια σύγκρουση, εμφανίζεται ένα παράθυρο "chooser" ώστε ο χρήστης να αποφασίσει.

Explicit Intents

Ένα explicit intent καθορίζει το όνομα της κλάσης που στοχεύει:

java
Intent downloadIntent = new (this, DownloadService.class):

Σε άλλες εφαρμογές, προκειμένου να αποκτήσετε πρόσβαση στην προηγουμένως δηλωμένη πρόθεση, μπορείτε να χρησιμοποιήσετε:

java
Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);

Pending Intents

Αυτά επιτρέπουν σε άλλες εφαρμογές να εκτελούν ενέργειες εκ μέρους της εφαρμογής σας, χρησιμοποιώντας την ταυτότητα και τις άδειες της εφαρμογής σας. Για να κατασκευάσετε ένα Pending Intent, θα πρέπει να καθοριστεί μια πρόθεση και η ενέργεια που θα εκτελεστεί. Εάν η δηλωμένη πρόθεση δεν είναι Explicit (δεν δηλώνει ποια πρόθεση μπορεί να την καλέσει), μια κακόβουλη εφαρμογή θα μπορούσε να εκτελέσει την δηλωμένη ενέργεια εκ μέρους της εφαρμογής-θύματος. Επιπλέον, εάν δεν καθοριστεί μια ενέργεια, η κακόβουλη εφαρμογή θα είναι σε θέση να εκτελέσει οποιαδήποτε ενέργεια εκ μέρους του θύματος.

Broadcast Intents

Σε αντίθεση με τις προηγούμενες προθέσεις, οι οποίες γίνονται δεκτές μόνο από μία εφαρμογή, οι broadcast intents μπορούν να γίνουν δεκτές από πολλές εφαρμογές. Ωστόσο, από την έκδοση API 14, είναι δυνατό να καθοριστεί η εφαρμογή που θα πρέπει να λάβει το μήνυμα χρησιμοποιώντας το Intent.setPackage.

Εναλλακτικά, είναι επίσης δυνατό να καθοριστεί μια άδεια κατά την αποστολή του broadcast. Η εφαρμογή παραλήπτης θα χρειαστεί να έχει αυτή την άδεια.

Υπάρχουν δύο τύποι Broadcasts: Normal (ασύγχρονα) και Ordered (σύγχρονα). Η σειρά βασίζεται στην καθορισμένη προτεραιότητα εντός του στοιχείου παραλήπτη. Κάθε εφαρμογή μπορεί να επεξεργαστεί, να μεταφέρει ή να απορρίψει το Broadcast.

Είναι δυνατό να σταλεί ένα broadcast χρησιμοποιώντας τη λειτουργία sendBroadcast(intent, receiverPermission) από την κλάση Context.
Μπορείτε επίσης να χρησιμοποιήσετε τη λειτουργία sendBroadcast από τον LocalBroadCastManager που διασφαλίζει ότι το μήνυμα δεν θα φύγει ποτέ από την εφαρμογή. Χρησιμοποιώντας αυτό, δεν θα χρειαστεί καν να εξάγετε ένα συστατικό παραλήπτη.

Sticky Broadcasts

Αυτού του είδους οι Broadcasts μπορούν να προσπελαστούν πολύ μετά την αποστολή τους.
Αυτά καταργήθηκαν στην έκδοση API 21 και συνιστάται να μην τα χρησιμοποιείτε.
Επιτρέπουν σε οποιαδήποτε εφαρμογή να υποκλέψει τα δεδομένα, αλλά και να τα τροποποιήσει.

Εάν βρείτε λειτουργίες που περιέχουν τη λέξη "sticky" όπως sendStickyBroadcast ή sendStickyBroadcastAsUser, ελέγξτε τον αντίκτυπο και προσπαθήστε να τις αφαιρέσετε.

Στις εφαρμογές Android, οι deep links χρησιμοποιούνται για να ξεκινήσουν μια ενέργεια (Intent) απευθείας μέσω μιας διεύθυνσης URL. Αυτό γίνεται δηλώνοντας ένα συγκεκριμένο URL scheme εντός μιας δραστηριότητας. Όταν μια συσκευή Android προσπαθεί να πρόσβαση σε μια διεύθυνση URL με αυτό το scheme, η καθορισμένη δραστηριότητα εντός της εφαρμογής εκκινείται.

Το scheme πρέπει να δηλωθεί στο αρχείο AndroidManifest.xml:

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>
[...]

Το σχήμα από το προηγούμενο παράδειγμα είναι examplescheme:// (σημειώστε επίσης την κατηγορία BROWSABLE)

Στη συνέχεια, στο πεδίο δεδομένων, μπορείτε να καθορίσετε τον host και την διαδρομή:

xml
<data android:scheme="examplescheme"
android:host="example"
/>

Για να αποκτήσετε πρόσβαση σε αυτό από τον ιστό, είναι δυνατόν να ορίσετε έναν σύνδεσμο όπως:

xml
<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>

Για να βρείτε τον κώδικα που θα εκτελείται στην Εφαρμογή, πηγαίνετε στην δραστηριότητα που καλείται από το deeplink και αναζητήστε τη συνάρτηση onNewIntent.

Μάθετε πώς να καλείτε deep links χωρίς να χρησιμοποιείτε σελίδες HTML.

AIDL - Γλώσσα Ορισμού Διεπαφής Android

Η Γλώσσα Ορισμού Διεπαφής Android (AIDL) έχει σχεδιαστεί για να διευκολύνει την επικοινωνία μεταξύ πελάτη και υπηρεσίας σε εφαρμογές Android μέσω διαδικαστικής επικοινωνίας (IPC). Δεδομένου ότι η άμεση πρόσβαση στη μνήμη άλλης διαδικασίας δεν επιτρέπεται στο Android, η AIDL απλοποιεί τη διαδικασία μαρσάροντας αντικείμενα σε μια μορφή που κατανοεί το λειτουργικό σύστημα, διευκολύνοντας έτσι την επικοινωνία μεταξύ διαφορετικών διαδικασιών.

Βασικές Έννοιες

  • Δεσμευμένες Υπηρεσίες: Αυτές οι υπηρεσίες χρησιμοποιούν AIDL για IPC, επιτρέποντας σε δραστηριότητες ή συστατικά να συνδεθούν σε μια υπηρεσία, να κάνουν αιτήματα και να λαμβάνουν απαντήσεις. Η μέθοδος onBind στην κλάση της υπηρεσίας είναι κρίσιμη για την έναρξη της αλληλεπίδρασης, καθιστώντας την μια ζωτική περιοχή για έλεγχο ασφαλείας στην αναζήτηση ευπαθειών.

  • Messenger: Λειτουργώντας ως δεσμευμένη υπηρεσία, ο Messenger διευκολύνει την IPC με έμφαση στην επεξεργασία δεδομένων μέσω της μεθόδου onBind. Είναι απαραίτητο να εξετάσετε αυτή τη μέθοδο προσεκτικά για οποιαδήποτε μη ασφαλή διαχείριση δεδομένων ή εκτέλεση ευαίσθητων συναρτήσεων.

  • Binder: Αν και η άμεση χρήση της κλάσης Binder είναι λιγότερο συνηθισμένη λόγω της αφαίρεσης της AIDL, είναι χρήσιμο να κατανοήσετε ότι ο Binder λειτουργεί ως οδηγός επιπέδου πυρήνα διευκολύνοντας τη μεταφορά δεδομένων μεταξύ των χώρων μνήμης διαφορετικών διαδικασιών. Για περαιτέρω κατανόηση, υπάρχει διαθέσιμος πόρος στο https://www.youtube.com/watch?v=O-UHvFjxwZ8.

Συστατικά

Αυτά περιλαμβάνουν: Δραστηριότητες, Υπηρεσίες, Δέκτες Εκπομπών και Παροχείς.

Δραστηριότητα Εκκίνησης και άλλες δραστηριότητες

Στις εφαρμογές Android, οι δραστηριότητες είναι σαν οθόνες, που δείχνουν διάφορα μέρη της διεπαφής χρήστη της εφαρμογής. Μια εφαρμογή μπορεί να έχει πολλές δραστηριότητες, καθεμία από τις οποίες παρουσιάζει μια μοναδική οθόνη στον χρήστη.

Η δραστηριότητα εκκίνησης είναι η κύρια πύλη σε μια εφαρμογή, που εκκινείται όταν πατάτε το εικονίδιο της εφαρμογής. Ορίζεται στο αρχείο μανιφέστ της εφαρμογής με συγκεκριμένα MAIN και LAUNCHER intents:

html
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Όχι όλες οι εφαρμογές χρειάζονται μια δραστηριότητα εκκίνησης, ειδικά αυτές χωρίς διεπαφή χρήστη, όπως οι υπηρεσίες φόντου.

Οι δραστηριότητες μπορούν να γίνουν διαθέσιμες σε άλλες εφαρμογές ή διεργασίες σημειώνοντάς τες ως "εξαγόμενες" στο μανιφέστο. Αυτή η ρύθμιση επιτρέπει σε άλλες εφαρμογές να ξεκινούν αυτή τη δραστηριότητα:

markdown
<service android:name=".ExampleExportedService" android:exported="true"/>

Ωστόσο, η πρόσβαση σε μια δραστηριότητα από άλλη εφαρμογή δεν είναι πάντα κίνδυνος ασφαλείας. Η ανησυχία προκύπτει αν ευαίσθητα δεδομένα μοιράζονται ακατάλληλα, κάτι που θα μπορούσε να οδηγήσει σε διαρροές πληροφοριών.

Ο κύκλος ζωής μιας δραστηριότητας ξεκινά με τη μέθοδο onCreate, ρυθμίζοντας το UI και προετοιμάζοντας τη δραστηριότητα για αλληλεπίδραση με τον χρήστη.

Υποκλάση Εφαρμογής

Στην ανάπτυξη Android, μια εφαρμογή έχει την επιλογή να δημιουργήσει μια υποκλάση της Application κλάσης, αν και δεν είναι υποχρεωτική. Όταν οριστεί μια τέτοια υποκλάση, γίνεται η πρώτη κλάση που θα δημιουργηθεί μέσα στην εφαρμογή. Η μέθοδος attachBaseContext, αν υλοποιηθεί σε αυτή την υποκλάση, εκτελείται πριν από τη μέθοδο onCreate. Αυτή η ρύθμιση επιτρέπει την πρώιμη αρχικοποίηση πριν ξεκινήσει το υπόλοιπο της εφαρμογής.

java
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
}
}

Υπηρεσίες

Υπηρεσίες είναι λειτουργίες παρασκηνίου ικανές να εκτελούν εργασίες χωρίς διεπαφή χρήστη. Αυτές οι εργασίες μπορούν να συνεχίσουν να εκτελούνται ακόμη και όταν οι χρήστες αλλάζουν σε διαφορετικές εφαρμογές, καθιστώντας τις υπηρεσίες κρίσιμες για μακροχρόνιες λειτουργίες.

Οι υπηρεσίες είναι ευέλικτες; μπορούν να ξεκινήσουν με διάφορους τρόπους, με τις Intents να είναι η κύρια μέθοδος για την εκκίνηση τους ως σημείο εισόδου μιας εφαρμογής. Μόλις ξεκινήσει μια υπηρεσία χρησιμοποιώντας τη μέθοδο startService, η μέθοδος onStart ενεργοποιείται και συνεχίζει να εκτελείται μέχρι να κληθεί ρητά η μέθοδος stopService. Εναλλακτικά, αν ο ρόλος μιας υπηρεσίας εξαρτάται από μια ενεργή σύνδεση πελάτη, χρησιμοποιείται η μέθοδος bindService για τη σύνδεση του πελάτη με την υπηρεσία, ενεργοποιώντας τη μέθοδο onBind για τη μεταφορά δεδομένων.

Μια ενδιαφέρουσα εφαρμογή των υπηρεσιών περιλαμβάνει την αναπαραγωγή μουσικής παρασκηνίου ή την ανάκτηση δεδομένων δικτύου χωρίς να εμποδίζεται η αλληλεπίδραση του χρήστη με μια εφαρμογή. Επιπλέον, οι υπηρεσίες μπορούν να γίνουν προσβάσιμες σε άλλες διεργασίες στην ίδια συσκευή μέσω εξαγωγής. Αυτό δεν είναι η προεπιλεγμένη συμπεριφορά και απαιτεί ρητή ρύθμιση στο αρχείο Android Manifest:

xml
<service android:name=".ExampleExportedService" android:exported="true"/>

Broadcast Receivers

Broadcast receivers λειτουργούν ως ακροατές σε ένα σύστημα μηνυμάτων, επιτρέποντας σε πολλές εφαρμογές να ανταποκριθούν στα ίδια μηνύματα από το σύστημα. Μια εφαρμογή μπορεί να καταχωρήσει έναν δέκτη με δύο κύριους τρόπους: μέσω του Manifest της εφαρμογής ή δυναμικά μέσα στον κώδικα της εφαρμογής μέσω του registerReceiver API. Στο Manifest, οι εκπομπές φιλτράρονται με άδειες, ενώ οι δυναμικά καταχωρημένοι δέκτες μπορούν επίσης να καθορίσουν άδειες κατά την καταχώρηση.

Intent filters είναι κρίσιμα και στους δύο τρόπους καταχώρησης, καθορίζοντας ποιες εκπομπές ενεργοποιούν τον δέκτη. Μόλις σταλεί μια αντίστοιχη εκπομπή, η μέθοδος onReceive του δέκτη καλείται, επιτρέποντας στην εφαρμογή να αντιδράσει αναλόγως, όπως η προσαρμογή της συμπεριφοράς σε απάντηση σε μια ειδοποίηση χαμηλής μπαταρίας.

Οι εκπομπές μπορεί να είναι είτε ασύγχρονες, φτάνοντας σε όλους τους δέκτες χωρίς σειρά, είτε σύγχρονες, όπου οι δέκτες λαμβάνουν την εκπομπή με βάση καθορισμένες προτεραιότητες. Ωστόσο, είναι σημαντικό να σημειωθεί ο πιθανός κίνδυνος ασφαλείας, καθώς οποιαδήποτε εφαρμογή μπορεί να δώσει προτεραιότητα στον εαυτό της για να παρεμποδίσει μια εκπομπή.

Για να κατανοήσετε τη λειτουργικότητα ενός δέκτη, αναζητήστε τη μέθοδο onReceive μέσα στην κλάση του. Ο κώδικας αυτής της μεθόδου μπορεί να χειριστεί το ληφθέν Intent, υπογραμμίζοντας την ανάγκη για επικύρωση δεδομένων από τους δέκτες, ειδικά σε Ordered Broadcasts, οι οποίες μπορούν να τροποποιήσουν ή να απορρίψουν το Intent.

Content Provider

Content Providers είναι απαραίτητοι για την κοινή χρήση δομημένων δεδομένων μεταξύ εφαρμογών, τονίζοντας τη σημασία της εφαρμογής αδειών για την εξασφάλιση της ασφάλειας των δεδομένων. Επιτρέπουν στις εφαρμογές να έχουν πρόσβαση σε δεδομένα από διάφορες πηγές, συμπεριλαμβανομένων βάσεων δεδομένων, συστημάτων αρχείων ή του διαδικτύου. Συγκεκριμένες άδειες, όπως readPermission και writePermission, είναι κρίσιμες για τον έλεγχο της πρόσβασης. Επιπλέον, μπορεί να παραχωρηθεί προσωρινή πρόσβαση μέσω ρυθμίσεων grantUriPermission στο manifest της εφαρμογής, εκμεταλλευόμενοι χαρακτηριστικά όπως path, pathPrefix και pathPattern για λεπτομερή έλεγχο πρόσβασης.

Η επικύρωση εισόδου είναι πρωταρχικής σημασίας για την αποφυγή ευπαθειών, όπως η SQL injection. Οι Content Providers υποστηρίζουν βασικές λειτουργίες: insert(), update(), delete(), και query(), διευκολύνοντας τη χειρισμό και την κοινή χρήση δεδομένων μεταξύ εφαρμογών.

FileProvider, ένας εξειδικευμένος Content Provider, επικεντρώνεται στην ασφαλή κοινή χρήση αρχείων. Ορίζεται στο manifest της εφαρμογής με συγκεκριμένα χαρακτηριστικά για τον έλεγχο της πρόσβασης σε φακέλους, που δηλώνονται με android:exported και android:resource που δείχνουν σε ρυθμίσεις φακέλων. Συνιστάται προσοχή κατά την κοινή χρήση καταλόγων για την αποφυγή της τυχαίας έκθεσης ευαίσθητων δεδομένων.

Example manifest declaration for FileProvider:

xml
<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:

xml
<paths>
<files-path path="images/" name="myimages" />
</paths>

Για περισσότερες πληροφορίες ελέγξτε:

WebViews

Τα WebViews είναι σαν μικροί περιηγητές ιστού μέσα σε εφαρμογές Android, αντλώντας περιεχόμενο είτε από το διαδίκτυο είτε από τοπικά αρχεία. Αντιμετωπίζουν παρόμοιους κινδύνους με τους κανονικούς περιηγητές, ωστόσο υπάρχουν τρόποι για μείωση αυτών των κινδύνων μέσω συγκεκριμένων ρυθμίσεων.

Η Android προσφέρει δύο κύριους τύπους WebView:

  • WebViewClient είναι εξαιρετικός για βασικό HTML αλλά δεν υποστηρίζει τη λειτουργία ειδοποίησης JavaScript, επηρεάζοντας τον τρόπο που μπορούν να δοκιμαστούν οι επιθέσεις XSS.
  • WebChromeClient λειτουργεί περισσότερο σαν την πλήρη εμπειρία του περιηγητή Chrome.

Ένα βασικό σημείο είναι ότι οι περιηγητές WebView δεν μοιράζονται cookies με τον κύριο περιηγητή της συσκευής.

Για τη φόρτωση περιεχομένου, είναι διαθέσιμες μέθοδοι όπως loadUrl, loadData και loadDataWithBaseURL. Είναι κρίσιμο να διασφαλιστεί ότι αυτές οι διευθύνσεις URL ή τα αρχεία είναι ασφαλή προς χρήση. Οι ρυθμίσεις ασφαλείας μπορούν να διαχειριστούν μέσω της κλάσης WebSettings. Για παράδειγμα, η απενεργοποίηση της JavaScript με setJavaScriptEnabled(false) μπορεί να αποτρέψει επιθέσεις XSS.

Η JavaScript "Bridge" επιτρέπει στα αντικείμενα Java να αλληλεπιδρούν με τη JavaScript, απαιτώντας οι μέθοδοι να είναι επισημασμένες με @JavascriptInterface για ασφάλεια από την Android 4.2 και μετά.

Η δυνατότητα πρόσβασης περιεχομένου (setAllowContentAccess(true)) επιτρέπει στα WebViews να προσεγγίζουν τους Content Providers, κάτι που θα μπορούσε να είναι κίνδυνος εκτός αν οι διευθύνσεις URL περιεχομένου επαληθευτούν ως ασφαλείς.

Για τον έλεγχο πρόσβασης σε αρχεία:

  • Η απενεργοποίηση της πρόσβασης σε αρχεία (setAllowFileAccess(false)) περιορίζει την πρόσβαση στο σύστημα αρχείων, με εξαιρέσεις για ορισμένα assets, διασφαλίζοντας ότι χρησιμοποιούνται μόνο για μη ευαίσθητο περιεχόμενο.

Άλλα Συστατικά Εφαρμογών και Διαχείριση Κινητών Συσκευών

Ψηφιακή Υπογραφή Εφαρμογών

  • Η ψηφιακή υπογραφή είναι απαραίτητη για τις εφαρμογές Android, διασφαλίζοντας ότι είναι αυθεντικά συγγραφείς πριν από την εγκατάσταση. Αυτή η διαδικασία χρησιμοποιεί ένα πιστοποιητικό για την αναγνώριση της εφαρμογής και πρέπει να επαληθευτεί από τον διαχειριστή πακέτων της συσκευής κατά την εγκατάσταση. Οι εφαρμογές μπορούν να είναι αυτο-υπογεγραμμένες ή πιστοποιημένες από εξωτερικό CA, προστατεύοντας από μη εξουσιοδοτημένη πρόσβαση και διασφαλίζοντας ότι η εφαρμογή παραμένει αμετάβλητη κατά την παράδοσή της στη συσκευή.

Επαλήθευση Εφαρμογών για Αυξημένη Ασφάλεια

  • Ξεκινώντας από την Android 4.2, μια δυνατότητα που ονομάζεται Verify Apps επιτρέπει στους χρήστες να ελέγχουν τις εφαρμογές για ασφάλεια πριν από την εγκατάσταση. Αυτή η διαδικασία επαλήθευσης μπορεί να προειδοποιήσει τους χρήστες για πιθανώς επιβλαβείς εφαρμογές ή ακόμη και να αποτρέψει την εγκατάσταση ιδιαίτερα κακόβουλων, ενισχύοντας την ασφάλεια του χρήστη.

Διαχείριση Κινητών Συσκευών (MDM)

  • Οι λύσεις MDM παρέχουν επίβλεψη και ασφάλεια για κινητές συσκευές μέσω του Device Administration API. Απαιτούν την εγκατάσταση μιας εφαρμογής Android για να διαχειρίζονται και να ασφαλίζουν αποτελεσματικά τις κινητές συσκευές. Οι βασικές λειτουργίες περιλαμβάνουν επιβολή πολιτικών κωδικών πρόσβασης, υποχρεωτική κρυπτογράφηση αποθήκευσης και άδεια απομακρυσμένης διαγραφής δεδομένων, διασφαλίζοντας πλήρη έλεγχο και ασφάλεια πάνω στις κινητές συσκευές.
java
// 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

Το Android Binder IPC εκθέτει πολλές υπηρεσίες συστήματος και προμηθευτών. Αυτές οι υπηρεσίες γίνονται μια επιφάνεια επίθεσης όταν εξάγονται χωρίς κατάλληλο έλεγχο δικαιωμάτων (η ίδια η στρώση AIDL δεν εκτελεί κανέναν έλεγχο πρόσβασης).

1. Ανακάλυψη τρεχουσών υπηρεσιών

bash
# from an adb shell (USB or wireless)
service list               # simple one-liner
am list services           # identical output, ActivityManager wrapper
  1. Εισαγωγή
  2. Βασικές έννοιες
  3. Τεχνικές hacking
  4. Εργαλεία και πόροι
  5. Στρατηγικές pentesting
  6. Συμπεράσματα
145  mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146  wifi             : [android.net.wifi.IWifiManager]
  • Ο δείκτης (πρώτη στήλη) ανατίθεται κατά την εκτέλεση – μην βασίζεστε σε αυτόν κατά τις επανεκκινήσεις.
  • Το όνομα Binder (π.χ. mtkconnmetrics) είναι αυτό που θα περαστεί στη service call.
  • Η τιμή μέσα στις αγκύλες είναι η πλήρως προσδιορισμένη διεπαφή AIDL από την οποία δημιουργήθηκε το stub.

2. Αποκτήστε τον περιγραφέα διεπαφής (PING)

Κάθε Binder stub υλοποιεί αυτόματα τον κωδικό συναλλαγής 0x5f4e5446 (1598968902 δεκαδικό, ASCII "_NTF").

bash
# "ping" the service
service call mtkconnmetrics 1    # 1 == decimal 1598968902 mod 2^32

Μια έγκυρη απάντηση επιστρέφει το όνομα διεπαφής κωδικοποιημένο ως UTF-16 string μέσα σε ένα Parcel.

3. Κλήση μιας συναλλαγής

Σύνταξη: service call <name> <code> [type value ...]

Κοινές καθοριστές παραμέτρων:

  • i32 <int> – υπογεγραμμένη τιμή 32-bit
  • i64 <long> – υπογεγραμμένη τιμή 64-bit
  • s16 <string> – UTF-16 string (Android 13+ χρησιμοποιεί utf16)

Παράδειγμα – ξεκινήστε την παρακολούθηση δικτύου με uid 1 σε μια συσκευή MediaTek:

bash
service call mtkconnmetrics 8 i32 1

4. Brute-forcing unknown methods

Όταν τα αρχεία κεφαλίδας δεν είναι διαθέσιμα, μπορείτε να επικαλείστε τον κώδικα μέχρι να αλλάξει το σφάλμα από:

Result: Parcel(00000000 00000000)  # "Not a data message"

σε μια κανονική Parcel απάντηση ή SecurityException.

bash
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 που υλοποιεί τη διεπαφή (για AOSP stubs ελέγξτε το /system/framework; οι OEMs συχνά χρησιμοποιούν το /system_ext ή το /vendor). Αναζητήστε το Stub.onTransact() – περιέχει ένα γιγαντιαίο switch(transactionCode):

java
case TRANSACTION_updateCtaAppStatus:      // 5
data.enforceInterface(DESCRIPTOR);
int appId  = data.readInt();
boolean ok = data.readInt() != 0;
updateCtaAppStatus(appId, ok);
reply.writeNoException();
return true;

Τώρα το πρωτότυπο και οι τύποι παραμέτρων είναι απολύτως σαφή.

6. Εντοπισμός ελλειπόντων ελέγχων άδειας

Η υλοποίηση (συχνά μια εσωτερική κλάση Impl) είναι υπεύθυνη για την εξουσιοδότηση:

java
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}

Η απουσία τέτοιας λογικής ή μιας λευκής λίστας προνομιακών UIDs (π.χ. uid == 1000 /*system*/) είναι ένας δείκτης ευπάθειας.

Μελέτη περίπτωσης – MediaTek startMonitorProcessWithUid() (συναλλαγή 8) εκτελεί πλήρως ένα μήνυμα Netlink χωρίς καμία πύλη άδειας, επιτρέποντας σε μια μη προνομιακή εφαρμογή να αλληλεπιδράσει με το module Netfilter του πυρήνα και να σπαμάρει το σύστημα καταγραφής.

7. Αυτοματοποίηση της αξιολόγησης

Εργαλεία / σενάρια που επιταχύνουν την αναγνώριση Binder:

  • binderfs – εκθέτει το /dev/binderfs με κόμβους ανά υπηρεσία
  • binder-scanner.py – διασχίζει τον πίνακα binder και εκτυπώνει ACLs
  • Συντόμευση Frida: Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))

Αναφορές

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