Android has the ContentProvider mechanism to allow
applications to share raw data. This can be implemented to share SQL
data, images, sounds, or whatever you like; the interface is obviously
designed to be used with a SQL backend, and one is even provided.
ContentProviders are implemented by applications to expose their data
to the rest of the system. The <provider> tag in the
application’s AndroidManifest.xml file registers a provider as
available and defines permissions for accessing it.
The Android
security documentation mentions that there can be separate read and
write permissions for reading and writing on a provider. It states that
“holding only the write permission does not mean you can read from a
provider” (Google, 2008).
People familiar with SQL will
probably realize that it isn’t generally possible to have write-only
SQL queries. For example, an updateQuery() or deleteQuery() call
results in the generation of a SQL statement in which a where clauses
is provided by the caller. This is true even if the caller has only
write permission. Controlling a where clause doesn’t directly return
data, but the ability to change a statement’s behavior based on the
stored data value effectively reveals it. Through watching the side
effects of a series of calls with clever where clauses, callers can
slowly reconstruct whatever data is stored. As an example of this,
attackers exploiting “blind” SQL injection flaws use this technique of
repeated queries on for flaws that don’t directly expose query results
in order to reconstruct the database of vulnerable systems. You could
certainly create a provider for which this is not the case, especially
if the provider is file
or memory based, but it isn’t likely that this will just work for
simple SQL-based providers. Keep this in mind before designing a system
that relies on write-only provider access.
Declare the read and
write permissions you wish enforced by the system directly in
AndroidMainfext.xml’s <provider> tag. These tags are
android:readPermission and android:writePermission. These permissions
are enforced at access time, subject to the limitations of the
implementations discussed earlier. A general permission tag needed for
any access can also be required.
Tip
Assume
clients with write access to a content provider also have read access.
Describe any write permission you create as granting read-write access
to SQL-based providers. Consider creating permissions like
ACCESS_RESOURCE rather than separate READ_RESOURCE and WRITE_ RESOURCE
permissions when dealing with SQL-based providers.
Implementing a provider
that is shared with other applications involves accepting some risks.
For example, will those other applications properly synchronize their
accesses of the data and send the right notifications on changes?
ContentProviders are very powerful, but you don’t always need all that
power. Consider simpler ways of coordinating data access where
convenient.
An advanced feature
providers may use is dynamic granting and revoking of access to other
programs. The programs granted access are identified by their package
name, which is the name they registered with the system on install (in
their <manifest> tags, android:package attribute). Packages are
granted temporary access to a particular Uniform Resource Identifier
(URI). Generally, granting this kind of access doesn’t seem like a
great idea, though, because the granting isn’t directly validated by
the user and there may not be correct restrictions on the query strings
the caller can use. Also, I haven’t worked with this option enough to
give advice about using it securely. It can be used by marking your
provider tag with the attribute android:grantUriPermissions=“true” and
a subsequent <grant-uri-permission> with attributes specifying
which URIs are permitted. (You can find the rather weak documentation
for this at http://code.google.com/android/reference/android/R.styleable.html#AndroidManifestGrantUriPermission.)
Providers may then use the grantUriPermission() and
revokeUriPermission() methods to give add and remove permissions
dynamically. The right can also be granted with special Intent flags:
FLAG_GRANT_READ_URI_PERMISSION and FLAG_GRANT_WRITE_URI_PERMISSION.
Code that does this kind of thing would be a great place to start
looking for security holes, although the open source Android code did
not use this feature as of version 1.5.