Securely sharing data via Content Providers
If your app is intended to share data with other apps then you should use a Content Provider to do so. This is the mechanism specifically provided within Android for this purpose.
The Android documentation provides a good introduction to Content Providers.
To secure a Content Provider you need to do two things:
Control access to the Content Provider through Android permissions. This was covered in week 3.
Guard against SQL injection for Content Providers that wrap SQLite databases (or any other database that supports SQL).
The parameterised methods provided by a Content Provider:
delete(), help guard against SQL injection.
However, we do need to pay attention to the
selection clauses passed to these methods, as carelessness here could result in SQL injection.
Where should the security barrier be?
There are two approaches we could take:
The implementation of the
delete()methods within the Content Provider could try to catch SQL injection attempts.
The caller of the
delete()methods within the client apps can block SQL injection attempts.
The choice depends upon where the threat is coming from. The first method puts the security barrier within the Content Provider, whereas the second method puts the security barrier within the clients of the Content Provider.
If the Content Provider is accessible by any app, or any app that the user grants permission to, then the security barrier needs to be within the Content Provider itself.
However, if access to the Content Provider is restricted to apps you know you can trust, then moving the security barrier into the client apps might make sense.
The technical stuff
At the technical level the solution is the same, the only difference is where the defensive code is placed: in the Content Provider, or in the calling app.
The key idea is the same as the one we saw in week 2 where we used parameterised queries to block SQL injection.
Inside the Content Provider the call to the
query() method will result in a corresponding query call on the database itself.
We need to ensure that the only user input that reaches that inner query is passed in the
selectionArgs array (of the inner call), with corresponding placeholders (parameters) in the actual SQL command.
The SQL command MUST NOT directly include any user input.
Our code can use the user input to select from a predefined hard-coded list of SQL commands, but not use the user input to construct the SQL command.
The Content Provider’s
query() method has the following signature.
Cursor query (Uri uri, String projection, String selection, String selectionArgs, String sortOrder)
If we place the security barrier within the Content Provider we need to ensure that the
selection parameters are not passed directly to the inner database query.
Alternatively, if we place the security barrier in the calling app, then the parameters
selection must not be directly constructed from user input.
© University of Southampton 2017