Content Provider
📌What is a content provider?
An Android Content Provider is a fundamental component of the Android operating system that enables different applications to share data with each other.
It acts as an interface that allows one application to securely expose its data to other applications, facilitating controlled and standardized access to the data.
Content providers are commonly used to manage structured data, such as databases, and consistently make that data available to other applications.
They enforce data security and provide a structured way for apps to CRUD data.
<provider android:name=".BookContentProvider" android:authorities="com.example.myapp.provider" android:exported="true" android:readPermission="com.example.myapp.READ_BOOKS" android:writePermission="com.example.myapp.WRITE_BOOKS"/>
📍Key features of Android Content Providers
Data Sharing: Content providers enable apps to share data without exposing the underlying database or implementation details.
Data Isolation: Content providers allow apps to define the level of access other apps have to their data. Access can be restricted to read-only, write-only, or both.
URI-Based Access: Data in a content provider is accessed using Uniform Resource Identifiers (URIs), which are similar to URLs and uniquely identify a resource within the content provider.
CRUD Operations: Content providers support basic CRUD (Create, Read, Update, Delete) operations for data management.
Data Types: Content providers can work with various types of data, including files, images, videos, and structured data stored in databases.
Permission Control: Apps that want to access data from a content provider must request the necessary permissions. This helps maintain security and control over data access.
📍Common use cases for content providers include
Contacts Data: Android's built-in Contacts app uses a content provider to manage and share contact information.
Media Files: Content providers are often used to manage media files like images, videos, and audio files, making them accessible to other apps.
SQLite Databases: Apps often use content providers to expose their SQLite databases for querying and manipulation.
📍Content Resolver and Content Provider
Content Provider: A content provider is created within the app that owns the database, allowing other apps to access this database.
Content Resolver: Any app wanting to access the database must use a content resolver to interact with the content provider.
The Content Resolver communicates with the Content Provider using specific methods.
The Content Resolver includes methods you can use for database queries and transactions. These methods correspond to those provided by the content provider:
query()insert()delete()update()
📍Security and Access Control
Permissions: Implement permissions to control who can access the data.
Exported vs. Non-Exported: Determined in the Android manifest, controlling external app access to the content provider.
📌How to access data?
A URI is used to uniquely identify and access a specific resource within a content provider. It points to a particular data resource within an app's content provider.
Here's the breakdown of a Content Provider URI:
content://: This scheme indicates that you're using a Content Provider URI.
authority: This is the unique identifier for the content provider, usually the package name of the app that owns it.
path: This part of the URI specifies the path to the specific resource you want to access within the content provider.
Database Content Provider:

📌How to access content providers?
📍Using adb shell
The Activity Manager (am) has a content provider, but this is not typically the best method for hackers.
For example, to query this URI (
content://com.android.contacts/1):
📍Use your own app
Using your application, you can define a content resolver to query data from other applications through their content providers.

How is this process done?
In your app, the content resolver sends a request to the content provider to retrieve the data.
If you have the necessary permissions and the provider is exported, the other app's content provider will return a cursor, which is a pointer to the requested data.
Now, the content resolver can use the available methods (
query,insert,update,delete) to interact with the database.Note: When working with custom content providers, the associated databases are stored in the
/data/datadirectory.
Using a content resolver in your app to query data from another app:
In the code above, the parameters are transformed into this SQL query:
The
querymethod parameters (query(contentUri, projection, null, null, null)) are ultimately transformed into a single SQL query, as shown below.

selection, selectionArgs, and sortOrder are optional filters for more complex queries. Here, they are null, meaning no additional filters are applied.
📌Hacking Content Provider
Testing
Check
AndroidManifest.xmlforandroid:exported="true".Analyze Methods in Java Code:
You need to inspect how the Content Provider implements:
query,insert,update, anddeletefor proper input sanitization.These methods often take user input (
where,selectionArgs) and build SQL queries.
Check file-handling methods like
openFile()for unvalidated URIs.
Identify Table Names
Search for
content://references in code to locate tables exposed via the Content Provider.When you find something like:
You can then try to query it.
Inspect URI handling logic for traversal issues.
If the app poorly validates the
Uriobjects passed intoopenFile(), orquery(), then you could:Read arbitrary files
Access data you shouldn’t
Use this command (
adb shell content query --uri URI) to display rows of data from the content provider's database that are accessible via the given URI.If it works without permission errors ➔ Vulnerable!
Hacking content providers using SQLI
📍Using adb shell
ADB allows you to interact directly with content providers through the
contentcommand, which can be used to perform CRUD operations.In this example, we’re accessing data from the
keytable, which is protected by custom user permission.So how can we circumvent this custom user permission using SQL Injection?
Let's imagine we have another table called
"Passwords"that doesn't require permissions. We could manipulate the query by modifying the projection, moving it to the end, and commenting out the rest. This might look like:The commands would be:
adb shellcontent query --uri content://com.example.app/Passwords --projection "* FROM Key--"
When attempting SQLI, the injected syntax must align with SQL rules. This means the injection needs to fit within the context of the original query structure to avoid errors.
This attack relies on having partial access to the database. However, most developers restrict direct access to the database entirely, reducing the risk.
📍Use your own app
Using your own application, you can define a content resolver to query data from other applications through their content providers.
If your app targets Android 11 (API level 30) or higher, this code may return
null. Why?Because you need to make your application visible to the target application.
To solve this, use the
<queries>element in theAndroidManifest.xmlfile:
📌If there are custom permissions, how can we bypass them?
First attempt:
Simply adding
////at the end of our content URI may bypass the restriction because of the missing regex validation for the path:
Second attempt (SQLI):
Steps
We need to query the Passwords table to insert our own SQL statement.
The SQL statement will be injected via the projection parameter.
The SQL syntax looks like
SELECT * FROM passwords WHERE....Projection ⇒
SELECT * FROM key--; FROM Passwords WHERE....
Code
Third attempt:
Access the protected table (Key) using the permissions declared in the
AndroidManifest.xmlfile.Steps
Define the permissions in our
AndroidManifest.xmlfile.Request these permissions during runtime.
Code
In the
AndroidManifest.xmlfile:In
MainActivity.java:
Hacking content providers using Path Traversal
As you know, content providers don’t only work with databases—they can also handle different types of files.
Steps to Identify:
Check Exported Providers: Ensure the Content Provider is exported.
ParcelFileDescriptorandopenFileMethod: When a content provider usesParcelFileDescriptorto open files (typically in theopenFilemethod), ensure that the URI input is validated.Unfiltered URI
Then you've got path traversal vulnerability
📌An Example:
We have a music app with an exported content provider in this example.
If we use our own app's content resolver to request an mp3 file, the music file will play, as shown below:

This might seem nice, right?
But what if we could somehow request access to a critical internal file? Would that still be safe?
For instance, if we query the URI for the file pin.xml by stepping back in the directory path (using ../) and adding the path of the file (../../../../../shared_prefs/pin.xml), the app's content provider might return the content of this critical file.

📍Use your own app
💡If the content provider is not exported, this entire approach becomes ineffective because you won’t be able to interact with it at all.
Last updated