The application was found to be vulnerable to SQL Injection targeting its content provider(s). This means that any application that simply requires this permission in its Android Manifest will be able to target the content provider and potentially retrieve data.
Android applications may use untrusted input to construct SQL queries in a way that is exploitable. The most common case is when applications do not sanitize input for any SQL statements and do not limit access to content providers. Any vulnerable content providers are listed in the Findings Evidence table.
Steps to Reproduce
Verify the permissions of the app's content providers. If a content provider was implemented with over-privileged permissions, these permissions need to be updated to the correct level. Permissions can be verified using the AndroidManifest. If a content provider has android:exported="true", verify its permission android:protectionLevel. If the protectionLevel has not been set or no permission has been set, then this provider may be vulnerable.
The NowSecure automated test for this finding sends a malicious payload to the app's content providers dynamically in order to determine if it can gain access to any SQL resources inside of the app.
Business Impact
The application has functionality which exposes stored data to other apps on the device. While this functionality may be necessary for the app to share data between other apps on the device, it can also allow malicious apps to expose that information and modify it in the context of the app. This may also expose sensitive user data.
Remediation Resources
Recommended Fix
When creating content providers, permissions are the best option to limit access to data provided by them. Setting android:exported=”false” in the AndroidManifests prevents the provider from being accessible by other apps. In cases where other apps need access to a provider, access should only be supplied to trusted apps using a android:protectionLevel=“signature”. For more information regarding content provider permissions, details can be found here: https://developer.android.com/training/articles/security-tips#ContentProviders.
When accessing a content provider, use parameterized query methods such as query(), update(), and delete() to avoid potential SQL injection from untrusted sources. Note that using parameterized methods is not sufficient if the selection argument is built by concatenating user data prior to submitting it to the method. Limiting permissions to read-only or write-only can also reduce the potential for harm related to SQL injection.
If you are using data within queries that are submitted to an SQL database or a content provider, ensure that the appropriate read and write permissions are correctly set for each vulnerable content provider. Details and code snippets can be found at https://developer.android.com/guide/topics/providers/content-provider-creating.
If you cannot use the security features above, we strongly recommend the use of well-structured data formats and verifying that the data conforms to the expected format. While blacklisting of characters or character-replacement can sometimes be an effective strategy, these techniques are error-prone in practice and should be avoided when possible.
Code Samples
Good Code Example (.java)
// Gets a word from the UI. searchWord is define elsewhere in the application
string userInput= searchWord.getText().toString();
// Query string where ? will be replaced using PreparedStatement which replaces the ? by the userInput. *GOOD CODE*
String query = "SELECT info FROM infoTable WHERE word = "+ userInput;
// build connection to server or database
Connection con = DriverManager.getConnection(connectionUrl);
// Use prepareStatement that parametrizes the userInput to replace the ? in the query
val statement = con.prepareStatement(query);
statement.setString(1, userInput);
var ResultSet result = statement.executeQuery();
// Additional Explanation:
// By creating a replaceable parameter '?' the user input is not bound directly to the query so it is not treated as a SQL and therefore cannot inject malicious SQL queries.
// It is always important to sanitize userInputs.
Good Code Example (.kotlin)
// Gets a word from the UI. searchWord is defined elsewhere in the application
var userInput= searchWord.getText().toString()
// Query string where ? will be replaced using PreparedStatement which replaces the ? by the userInput. *GOOD CODE*
var query = "SELECT info FROM infoTable WHERE word = "+ userInput;
// build connection to server or database. connectionUrl defined elsewhere in application
val con = DriverManager.getConnection(connectionUrl) as Connection
// Use prepareStatement that parametrizes the userInput to replace the ? in the query
val statement = con.prepareStatement(query)
statement.setString(1, userInput)
var result = statement.executeQuery() as ResultSet
// Additional Explanation:
// By creating a replaceable parameter '?' the user input is not bound directly to the query so it is not treated as a SQL and therefore cannot inject malicious SQL queries.
// It is always important to sanitize user inputs.
Finding Description
The application was found to be vulnerable to SQL Injection targeting its content provider(s). This means that any application that simply requires this permission in its Android Manifest will be able to target the content provider and potentially retrieve data. Android applications may use untrusted input to construct SQL queries in a way that is exploitable. The most common case is when applications do not sanitize input for any SQL statements and do not limit access to content providers. Any vulnerable content providers are listed in the Findings Evidence table.
Steps to Reproduce
Verify the permissions of the app's content providers. If a content provider was implemented with over-privileged permissions, these permissions need to be updated to the correct level. Permissions can be verified using the AndroidManifest. If a content provider has
android:exported="true"
, verify its permissionandroid:protectionLevel
. If the protectionLevel has not been set or no permission has been set, then this provider may be vulnerable. The NowSecure automated test for this finding sends a malicious payload to the app's content providers dynamically in order to determine if it can gain access to any SQL resources inside of the app.Business Impact
The application has functionality which exposes stored data to other apps on the device. While this functionality may be necessary for the app to share data between other apps on the device, it can also allow malicious apps to expose that information and modify it in the context of the app. This may also expose sensitive user data.
Remediation Resources
Recommended Fix
When creating content providers, permissions are the best option to limit access to data provided by them. Setting
android:exported=”false”
in the AndroidManifests prevents the provider from being accessible by other apps. In cases where other apps need access to a provider, access should only be supplied to trusted apps using aandroid:protectionLevel=“signature”
. For more information regarding content provider permissions, details can be found here: https://developer.android.com/training/articles/security-tips#ContentProviders. When accessing a content provider, use parameterized query methods such asquery()
,update()
, anddelete()
to avoid potential SQL injection from untrusted sources. Note that using parameterized methods is not sufficient if the selection argument is built by concatenating user data prior to submitting it to the method. Limiting permissions to read-only or write-only can also reduce the potential for harm related to SQL injection. If you are using data within queries that are submitted to an SQL database or a content provider, ensure that the appropriate read and write permissions are correctly set for each vulnerable content provider. Details and code snippets can be found at https://developer.android.com/guide/topics/providers/content-provider-creating. If you cannot use the security features above, we strongly recommend the use of well-structured data formats and verifying that the data conforms to the expected format. While blacklisting of characters or character-replacement can sometimes be an effective strategy, these techniques are error-prone in practice and should be avoided when possible.Code Samples
Good Code Example (.java)
Good Code Example (.kotlin)
Additional Guidance
Risk and Regulatory Information
Severity: medium CVSS: 5.7
Application
See more detail in the NowSecure Report