Android Applications Basics

Unterstützen Sie HackTricks

Android-Sicherheitsmodell

Es gibt zwei Ebenen:

  • Das Betriebssystem, das installierte Anwendungen voneinander isoliert.

  • Die Anwendung selbst, die es Entwicklern ermöglicht, bestimmte Funktionen freizugeben und die Anwendungsfähigkeiten zu konfigurieren.

UID-Trennung

Jede Anwendung erhält eine spezifische Benutzer-ID. Dies geschieht während der Installation der App, sodass die App nur mit Dateien interagieren kann, die ihrer Benutzer-ID gehören oder freigegebene Dateien sind. Daher können nur die App selbst, bestimmte Komponenten des Betriebssystems und der Root-Benutzer auf die Anwendungsdaten zugreifen.

UID-Sharing

Zwei Anwendungen können so konfiguriert werden, dass sie dieselbe UID verwenden. Dies kann nützlich sein, um Informationen zu teilen, aber wenn eine von ihnen kompromittiert wird, sind die Daten beider Anwendungen gefährdet. Aus diesem Grund wird dieses Verhalten abgeraten. Um dieselbe UID zu teilen, müssen Anwendungen denselben android:sharedUserId-Wert in ihren Manifests definieren.

Sandboxing

Der Android-Anwendungssandbox ermöglicht es, jede Anwendung als separaten Prozess unter einer separaten Benutzer-ID auszuführen. 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 erstellte dann Richtlinien, um nur die erwarteten Interaktionen zwischen ihnen zuzulassen.

Berechtigungen

Wenn Sie eine App installieren und sie nach Berechtigungen fragt, fragt die App nach den Berechtigungen, die in den uses-permission-Elementen in der AndroidManifest.xml-Datei konfiguriert sind. Das uses-permission-Element gibt den Namen der angeforderten Berechtigung im name-Attribut an. Es hat auch das maxSdkVersion-Attribut, das das Anfordern von Berechtigungen in Versionen über der angegebenen stoppt. Beachten Sie, dass Android-Anwendungen nicht alle Berechtigungen zu Beginn anfordern müssen; sie können auch dynamisch nach Berechtigungen fragen, aber alle Berechtigungen müssen im Manifest deklarieren.

Wenn eine App Funktionen freigibt, kann sie den Zugriff nur auf Apps beschränken, die über eine bestimmte Berechtigung verfügen. Ein Berechtigungselement hat drei Attribute:

  • Der Name der Berechtigung

  • Das permission-group-Attribut, das das Gruppieren verwandter Berechtigungen ermöglicht.

  • Das protection-level, das angibt, wie die Berechtigungen gewährt werden. Es gibt vier Typen:

  • Normal: Wird verwendet, wenn es keine bekannten Bedrohungen für die App gibt. Der Benutzer muss es nicht genehmigen.

  • Dangerous: Gibt an, dass die Berechtigung der anfordernden Anwendung einen erhöhten Zugriff gewährt. Benutzer werden gebeten, sie zu genehmigen.

  • Signature: Nur Apps, die mit demselben Zertifikat wie das, das die Komponente exportiert, signiert sind, können die Berechtigung erhalten. Dies ist die stärkste Art des Schutzes.

  • SignatureOrSystem: Nur **Apps, die mit demselben Zertifikat wie das, das die Komponente exportiert, signiert sind, oder Apps, die mit Systemzugriff ausgeführt werden, können Berechtigungen erhalten.

Vorinstallierte Anwendungen

Diese Apps befinden sich normalerweise in den /system/app oder /system/priv-app Verzeichnissen, und einige von ihnen sind optimiert (Sie finden möglicherweise nicht einmal die classes.dex-Datei). Diese Anwendungen sind es wert, überprüft zu werden, da sie manchmal mit zu vielen Berechtigungen (als Root) ausgeführt werden.

  • Die mit dem AOSP (Android OpenSource Project) ROM gelieferten

  • Vom Gerätehersteller hinzugefügt

  • Vom Mobilfunkanbieter hinzugefügt (wenn sie von ihnen gekauft wurden)

Rooting

Um Root-Zugriff auf ein physisches Android-Gerät zu erhalten, müssen Sie in der Regel 1 oder 2 Schwachstellen ausnutzen, die normalerweise spezifisch für das Gerät und die Version sind. Sobald der Exploit funktioniert hat, wird normalerweise die Linux su-Binärdatei an einem Ort kopiert, der in der PATH-Umgebungsvariablen des Benutzers angegeben ist, wie z.B. /system/xbin.

Sobald die su-Binärdatei konfiguriert ist, wird eine andere Android-App verwendet, um mit der su-Binärdatei zu interagieren und Anfragen für Root-Zugriff wie Superuser und SuperSU (verfügbar im Google Play Store) zu verarbeiten.

Beachten Sie, dass der Rooting-Prozess sehr gefährlich ist und das Gerät schwer beschädigen kann.

ROMs

Es ist möglich, das Betriebssystem durch die Installation einer benutzerdefinierten Firmware zu ersetzen. Dadurch ist es möglich, die Nützlichkeit eines alten Geräts zu erweitern, Softwarebeschränkungen zu umgehen oder Zugriff auf den neuesten Android-Code zu erhalten. OmniROM und LineageOS sind zwei der beliebtesten Firmwares.

Beachten Sie, 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 eine gut dokumentierte und sichere Weise.

Auswirkungen

Sobald ein Gerät gerootet ist, kann jede App Zugriff als Root anfordern. Wenn eine bösartige Anwendung dies erhält, hat sie Zugriff auf fast alles und kann das Telefon beschädigen.

Grundlagen der Android-Anwendung

  • Das Format von Android-Anwendungen wird als APK-Dateiformat bezeichnet. Es ist im Wesentlichen eine ZIP-Datei (durch Umbenennen der Dateierweiterung in .zip können die Inhalte extrahiert und angezeigt werden).

  • APK-Inhalte (nicht erschöpfend)

  • AndroidManifest.xml

  • resources.arsc/strings.xml

  • resources.arsc: enthält vorkompilierte Ressourcen, wie binäres XML.

  • 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/

  • Beherbergt native Bibliotheken, die nach CPU-Architektur in Unterverzeichnissen segregiert sind.

  • armeabi: Code für ARM-basierte Prozessoren

  • armeabi-v7a: Code für ARMv7 und höher basierte Prozessoren

  • x86: Code für X86-Prozessoren

  • mips: Code nur für MIPS-Prozessoren

  • assets/

  • Speichert verschiedene Dateien, die von der App benötigt werden, möglicherweise einschließlich zusätzlicher nativer 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 wird Java oder Kotlin zur Erstellung von Apps verwendet. Anstelle der Verwendung der JVM wie bei Desktop-Apps kompiliert Android diesen Code in Dalvik Executable (DEX) Bytecode. Früher verwaltete die Dalvik-VM diesen Bytecode, aber jetzt übernimmt die Android Runtime (ART) in neueren Android-Versionen.

Für die Rückentwicklung wird Smali entscheidend. Es ist die menschenlesbare Version von DEX-Bytecode und fungiert wie eine Assemblersprache, indem es Quellcode in Bytecode-Anweisungen übersetzt. Smali und baksmali beziehen sich in diesem Kontext auf die Assemblierungs- und Disassemblierungswerkzeuge.

Intents

Intents sind das primäre Mittel, durch das Android-Apps zwischen ihren Komponenten oder mit anderen Apps kommunizieren. Diese Nachrichtenobjekte können auch Daten zwischen Apps oder Komponenten übertragen, ähnlich wie GET/POST-Anfragen in HTTP-Kommunikationen verwendet werden.

Ein Intent ist also im Grunde eine Nachricht, die zwischen Komponenten übergeben wird. Intents können an bestimmte Komponenten oder Apps gerichtet werden, oder ohne einen bestimmten Empfänger gesendet werden. Einfach gesagt, kann ein Intent verwendet werden:

  • Um eine Aktivität zu starten, typischerweise um eine Benutzeroberfläche für eine App zu öffnen

  • Als Broadcasts, um das System und Apps über Änderungen zu informieren

  • Um einen Hintergrunddienst zu starten, zu stoppen und mit ihm zu kommunizieren

  • Um auf Daten über ContentProviders zuzugreifen

  • Als Rückrufe zur Behandlung von Ereignissen

Wenn sie anfällig sind, können Intents verwendet werden, um eine Vielzahl von Angriffen durchzuführen.

Intent-Filter

Intent-Filter definieren, wie eine Aktivität, ein Dienst oder ein Broadcast-Empfänger mit verschiedenen Arten von Intents interagieren kann. Im Wesentlichen beschreiben sie die Fähigkeiten dieser Komponenten, wie 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 innerhalb der AndroidManifest.xml-Datei, obwohl es auch eine Option ist, sie für Broadcast-Empfänger zu codieren.

Intent-Filter bestehen aus Kategorien, Aktionen und Datenfiltern, mit der Möglichkeit, zusätzliche Metadaten einzuschließen. Diese Konfiguration ermöglicht es Komponenten, spezifische Intents zu verarbeiten, die den deklarierten Kriterien entsprechen.

Ein kritischer Aspekt von Android-Komponenten (Aktivitäten/Dienste/Inhaltsanbieter/Broadcast-Empfänger) ist ihre Sichtbarkeit oder öffentlicher Status. Eine Komponente wird als öffentlich angesehen und kann mit anderen Apps interagieren, wenn sie exported mit einem Wert von true oder wenn ein Intent-Filter für sie im Manifest deklariert ist. Es gibt jedoch eine Möglichkeit für Entwickler, diese Komponenten ausdrücklich privat zu halten, um sicherzustellen, dass sie nicht unbeabsichtigt mit anderen Apps interagieren. Dies wird erreicht, indem das exported-Attribut in ihren Manifestdefinitionen auf false gesetzt wird.

Darüber hinaus haben Entwickler die Möglichkeit, den Zugriff auf diese Komponenten weiter abzusichern, indem sie spezifische Berechtigungen verlangen. Das permission-Attribut kann so eingestellt werden, dass nur Apps mit der vorgesehenen Berechtigung auf die Komponente zugreifen können, was eine zusätzliche Sicherheitsebene und Kontrolle darüber hinzufügt, wer mit ihr interagieren kann.

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

Implizite Intents

Intents werden programmgesteuert 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 ein 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 Aktion, Daten und Kategorie übereinstimmen, um eine Nachricht zu empfangen.

Der Prozess der "Intent-Auflösung" bestimmt, welche App jede Nachricht empfangen soll. Dieser Prozess berücksichtigt das Prioritätsattribut, das in der intent-filter-Deklaration festgelegt werden kann, und diejenige mit der höheren Priorität wird ausgewählt. Diese Priorität kann zwischen -1000 und 1000 festgelegt werden, und Anwendungen können den Wert SYSTEM_HIGH_PRIORITY verwenden. Wenn ein Konflikt auftritt, erscheint ein "Chooser"-Fenster, damit der Benutzer entscheiden kann.

Explizite Intents

Ein expliziter Intent gibt den Klassennamen an, den er anvisiert:

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

In anderen Anwendungen, um auf das zuvor deklarierte Intent zuzugreifen, können Sie 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, unter Verwendung der Identität und Berechtigungen Ihrer App. Beim Erstellen eines Pending Intent sollte ein Intent und die auszuführende Aktion angegeben werden. Wenn der deklarierte Intent nicht explizit ist (nicht angibt, welcher Intent ihn aufrufen kann), könnte eine bösartige Anwendung die deklarierte Aktion im Namen der Opfer-App ausführen. Darüber hinaus, wenn keine Aktion angegeben ist, kann die bösartige App jede Aktion im Namen des Opfers durchfü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. Ab API-Version 14 ist es jedoch möglich, die App anzugeben, die die Nachricht empfangen soll, indem man Intent.setPackage verwendet.

Alternativ ist es auch möglich, eine Berechtigung beim Senden des Broadcasts anzugeben. Die empfangende App muss diese Berechtigung haben.

Es gibt zwei Arten von Broadcasts: Normal (asynchron) und Ordered (synchron). Die Reihenfolge basiert auf der konfigurierten Priorität innerhalb des Empfängerelements. 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. Sie könnten auch die Funktion sendBroadcast von LocalBroadCastManager verwenden, die sicherstellt, dass die Nachricht die App niemals verlässt. Damit müssen Sie nicht einmal eine Empfangskomponente exportieren.

Sticky Broadcasts

Diese Art von Broadcasts kann lange nach dem Senden abgerufen werden. Diese wurden in API-Stufe 21 als veraltet erklärt und es wird empfohlen, sie nicht zu verwenden. Sie ermöglichen es jeder Anwendung, die Daten abzuhören, aber auch sie zu ä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.

In Android-Anwendungen werden Deep Links verwendet, um eine Aktion (Intent) direkt über eine URL zu initiieren. Dies geschieht durch die Deklaration eines spezifischen URL-Schemas innerhalb einer Aktivität. Wenn ein Android-Gerät versucht, auf eine URL mit diesem Schema zuzugreifen, wird die angegebene Aktivität 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 exampleapp:// (beachten Sie auch die category BROWSABLE)

Dann können Sie im Datenfeld den host und den path angeben:

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

Um von einer Webseite darauf zuzugreifen, ist es möglich, einen Link wie folgt zu setzen:

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

Um den Code zu finden, der in der App ausgeführt wird, gehen Sie zur Aktivität, die durch den Deeplink aufgerufen wird, und suchen Sie die Funktion onNewIntent.

Erfahren Sie, wie Sie Deep Links ohne Verwendung von HTML-Seiten aufrufen.

AIDL - Android Interface Definition Language

Die Android Interface Definition Language (AIDL) wurde entwickelt, um die Kommunikation zwischen Client und Dienst in Android-Anwendungen durch interprozessuale Kommunikation (IPC) zu erleichtern. Da der direkte Zugriff auf den Speicher eines anderen Prozesses auf Android nicht erlaubt ist, vereinfacht AIDL den Prozess, indem Objekte in ein vom Betriebssystem verstandenes Format umgewandelt werden, wodurch die Kommunikation zwischen verschiedenen Prozessen erleichtert wird.

Schlüsselkonzepte

  • Gebundene Dienste: Diese Dienste nutzen AIDL für IPC, wodurch Aktivitäten oder Komponenten an einen Dienst binden, Anfragen stellen und Antworten erhalten können. Die Methode onBind in der Dienstklasse ist entscheidend für den Beginn der Interaktion und stellt einen wichtigen Bereich für die Sicherheitsüberprüfung auf Schwachstellen dar.

  • Messenger: Als gebundener Dienst ermöglicht der Messenger IPC mit einem Fokus auf die Verarbeitung von Daten durch die Methode onBind. Es ist wichtig, diese Methode genau auf unsichere Datenverarbeitung oder die Ausführung sensibler Funktionen zu überprüfen.

  • Binder: Obwohl die direkte Verwendung der Binder-Klasse aufgrund der Abstraktion durch AIDL weniger verbreitet ist, ist es vorteilhaft zu verstehen, dass der Binder als Kernel-Treiber fungiert, der den Datentransfer zwischen den Speicherbereichen verschiedener Prozesse erleichtert. Für ein besseres Verständnis steht eine Ressource zur Verfügung unter https://www.youtube.com/watch?v=O-UHvFjxwZ8.

Komponenten

Diese umfassen: Aktivitäten, Dienste, Broadcast-Empfänger und Anbieter.

Launcher-Aktivität und andere Aktivitäten

In Android-Apps sind Aktivitäten wie Bildschirme, die verschiedene Teile der Benutzeroberfläche der App anzeigen. Eine App kann viele Aktivitäten haben, von denen jede einen einzigartigen Bildschirm für den Benutzer präsentiert.

Die Launcher-Aktivität ist das Haupttor zu einer App, das gestartet wird, wenn Sie auf das App-Symbol tippen. Sie ist in der Manifestdatei der App mit 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-Aktivität, insbesondere solche ohne Benutzeroberfläche, wie Hintergrunddienste.

Aktivitäten können anderen Apps oder Prozessen zur Verfügung gestellt werden, indem sie im Manifest als "exportiert" markiert werden. Diese Einstellung ermöglicht es anderen Apps, diese Aktivität zu starten:

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

Jedoch ist der Zugriff auf eine Aktivität von einer anderen App nicht immer ein Sicherheitsrisiko. Die Bedenken entstehen, wenn sensible Daten unsachgemäß geteilt werden, was zu Informationslecks führen könnte.

Der Lebenszyklus einer Aktivität beginnt mit der onCreate-Methode, die die Benutzeroberfläche einrichtet und die Aktivität auf die Interaktion mit dem Benutzer vorbereitet.

Anwendungssubklasse

In der Android-Entwicklung hat eine App die Möglichkeit, eine Subklasse der Application-Klasse zu erstellen, obwohl dies nicht obligatorisch ist. Wenn eine solche Subklasse definiert ist, wird sie die erste Klasse, die innerhalb der App instanziiert wird. Die attachBaseContext-Methode, wenn sie in dieser Subklasse implementiert ist, wird vor der onCreate-Methode ausgeführt. Diese Einrichtung 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
}
}

Dienste

Dienste sind Hintergrundoperationen, die in der Lage sind, Aufgaben ohne Benutzeroberfläche auszuführen. Diese Aufgaben können weiterhin ausgeführt werden, selbst wenn Benutzer zu anderen Anwendungen wechseln, was Dienste entscheidend für langandauernde Operationen macht.

Dienste sind vielseitig; sie können auf verschiedene Weise gestartet werden, wobei Intents die primäre Methode zum Starten als Einstiegspunkt einer Anwendung sind. Sobald ein Dienst mit der Methode startService gestartet wird, wird die Methode onStart aktiviert und läuft weiter, bis die Methode stopService ausdrücklich aufgerufen wird. Alternativ, wenn die Rolle eines Dienstes von einer aktiven Clientverbindung abhängt, wird die Methode bindService verwendet, um den Client mit dem Dienst zu verbinden, wobei die Methode onBind für den Datenaustausch aktiviert wird.

Eine interessante Anwendung von Diensten umfasst die Wiedergabe von Hintergrundmusik oder das Abrufen von Netzwerkdaten, ohne die Interaktion des Benutzers mit einer App zu behindern. Darüber hinaus können Dienste für andere Prozesse auf demselben Gerät durch Exportieren 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 Messaging-System und ermöglichen es mehreren Anwendungen, auf dieselben Nachrichten des Systems zu reagieren. Eine App kann einen Empfänger registrieren auf zwei Hauptarten: über das Manifest der App oder dynamisch im Code der App über die registerReceiver API. Im Manifest werden Broadcasts mit Berechtigungen gefiltert, während dynamisch registrierte Empfänger auch Berechtigungen bei der Registrierung angeben können.

Intent-Filter sind entscheidend in beiden Registrierungsarten, da sie bestimmen, welche Broadcasts den Empfänger auslösen. Sobald ein passender Broadcast gesendet wird, wird die Methode onReceive des Empfängers aufgerufen, was der App ermöglicht, entsprechend zu reagieren, z. B. das Verhalten als Reaktion auf eine Warnung bei niedrigem Batteriestand anzupassen.

Broadcasts können entweder asynchron sein, wobei alle Empfänger ohne Reihenfolge erreicht werden, oder synchron, wobei Empfänger den Broadcast basierend auf festgelegten Prioritäten erhalten. Es ist jedoch wichtig, das potenzielle Sicherheitsrisiko zu beachten, da jede App sich selbst priorisieren kann, um einen Broadcast abzufangen.

Um die Funktionalität eines Empfängers zu verstehen, suchen Sie nach der Methode onReceive innerhalb seiner Klasse. Der Code dieser Methode kann das empfangene Intent manipulieren, was die Notwendigkeit der Datenvalidierung durch Empfänger hervorhebt, insbesondere bei geordneten Broadcasts, die das Intent modifizieren oder verwerfen können.

Content Provider

Content Providers sind entscheidend für das Teilen strukturierter Daten zwischen Apps und betonen die Bedeutung der Implementierung von Berechtigungen, um die Datensicherheit zu gewährleisten. Sie ermöglichen es Apps, auf Daten aus verschiedenen Quellen zuzugreifen, einschließlich Datenbanken, Dateisystemen oder dem Web. Spezifische Berechtigungen wie readPermission und writePermission sind entscheidend für die Kontrolle des Zugriffs. Darüber hinaus kann temporärer Zugriff über grantUriPermission-Einstellungen im Manifest der App gewährt werden, wobei Attribute wie path, pathPrefix und pathPattern für eine detaillierte Zugriffskontrolle genutzt werden.

Die Eingangsvalidierung ist von größter Bedeutung, um Schwachstellen wie SQL-Injection zu verhindern. Content Providers unterstützen grundlegende Operationen: insert(), update(), delete() und query(), die die Datenmanipulation und das Teilen zwischen Anwendungen erleichtern.

FileProvider, ein spezialisierter Content Provider, konzentriert sich auf das sichere Teilen von Dateien. Er wird im Manifest der App mit spezifischen Attributen definiert, um den Zugriff auf Ordner zu steuern, die durch android:exported und android:resource auf Ordnerkonfigurationen verweisen. Vorsicht ist geboten, wenn Verzeichnisse geteilt werden, um zu vermeiden, dass sensible Daten unbeabsichtigt offengelegt werden.

Beispiel für die Manifestdeklaration für 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 für die Angabe von freigegebenen Ordnern in filepaths.xml:

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

Für weitere Informationen siehe:

WebViews

WebViews sind wie Mini-Webbrowser in Android-Apps, die Inhalte entweder aus dem Web oder von lokalen Dateien abrufen. Sie sind ähnlichen Risiken wie reguläre Browser ausgesetzt, jedoch gibt es Möglichkeiten, diese Risiken zu reduzieren durch spezifische Einstellungen.

Android bietet zwei Haupttypen von WebView:

  • WebViewClient ist großartig für grundlegendes HTML, unterstützt jedoch nicht die JavaScript-Alert-Funktion, was die Testmöglichkeiten für XSS-Angriffe beeinflusst.

  • WebChromeClient bietet mehr das volle Chrome-Browser-Erlebnis.

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. Sicherheitseinstellungen können über die WebSettings-Klasse verwaltet werden. Beispielsweise kann das Deaktivieren von JavaScript mit setJavaScriptEnabled(false) XSS-Angriffe verhindern.

Die JavaScript "Bridge" ermöglicht es Java-Objekten, mit JavaScript zu interagieren, wobei Methoden ab Android 4.2 mit @JavascriptInterface für die Sicherheit gekennzeichnet werden müssen.

Das Zulassen des Zugriffs auf Inhalte (setAllowContentAccess(true)) ermöglicht es WebViews, auf Content Providers zuzugreifen, was ein Risiko darstellen könnte, es sei denn, die Inhalts-URLs werden als sicher verifiziert.

Um den Dateizugriff zu steuern:

  • Das Deaktivieren des Dateizugriffs (setAllowFileAccess(false)) beschränkt den Zugriff auf das Dateisystem, mit Ausnahmen für bestimmte Assets, um sicherzustellen, dass sie nur für nicht sensible Inhalte verwendet werden.

Andere App-Komponenten und Mobile Device Management

Digitale Signatur von Anwendungen

  • Digitale Signaturen sind ein Muss für Android-Apps, um sicherzustellen, dass sie authentisch erstellt wurden, bevor sie installiert werden. Dieser Prozess verwendet ein Zertifikat zur Identifizierung der App und muss vom Paketmanager des Geräts bei der Installation verifiziert werden. Apps können selbstsigniert oder von einer externen CA zertifiziert sein, um unbefugten Zugriff zu verhindern und sicherzustellen, dass die App während der Lieferung an das Gerät unverändert bleibt.

App-Verifizierung für erhöhte Sicherheit

  • Ab Android 4.2 ermöglicht eine Funktion namens Apps überprüfen, dass Benutzer Apps vor der Installation auf Sicherheit überprüfen lassen. Dieser Verifizierungsprozess kann Benutzer vor potenziell schädlichen Apps warnen oder sogar die Installation besonders bösartiger Apps verhindern, was die Sicherheit der Benutzer erhöht.

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 zu sichern. Zu den Hauptfunktionen gehören Durchsetzung von Passwort-Richtlinien, Vorgabe von Speicher-Verschlüsselung und Erlauben von Remote-Datenlöschung, um umfassende Kontrolle und Sicherheit über mobile Geräte zu gewährleisten.

// 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);
}
Unterstütze HackTricks

Last updated