public abstract class SafeContentResolver
extends java.lang.Object
ContentResolver that protects against the Surreptitious Sharing attack when
opening file:// URIs.
When performing a Surreptitious Sharing attack a malicious app tries to trick the user into sending a file private to the target app to an attacker.
Example:
An Intent.ACTION_SEND intent that contains the attacker's email address as recipient and a file://
URI pointing to the file the email client uses to store account passwords. The attacking app itself doesn't have
access to this file because Android's security model prevents that. However, the email client has no trouble
opening a file that belongs to itself. If the user believes this to be a legitimate email with a legitimate
attachment, e.g. because the malicious app asked them to send a bug report, they will send the email and thereby
unknowingly expose their email account passwords to the attacker.
If your app is a receiver of such Intents and you want to protect against this attack, replace all
occurrences of ContentResolver.openInputStream(Uri) with openInputStream(Uri)
from this class. SafeContentResolver will refuse to open file:// URIs pointing to files belonging to
this app and content:// URIs belonging to ContentProviders of this app.
If you wish to allow access to certain content providers of your app, add the following <meta-data> element
to the appropriate <provider> entries in your manifest:
<provider …>
<meta-data
android:name="de.cketti.safecontentresolver.ALLOW_INTERNAL_ACCESS"
android:value="true" />
</provider>
On older Android versions apps have the ability to create hard
links to files they don't have read or write access to. That means we can't simply check the absolute file path
to learn if a file is stored in our own app-private directory. Instead, we use the fstat system call to
retrieve the User ID the file belongs to. And if it's identical to the UID of this process, access is denied.
| Modifier | Constructor and Description |
|---|---|
protected |
SafeContentResolver(android.content.Context context) |
| Modifier and Type | Method and Description |
|---|---|
protected abstract int |
getFileUidOrThrow(java.io.FileDescriptor fileDescriptor) |
static SafeContentResolver |
newInstance(android.content.Context context)
Create a
SafeContentResolver instance. |
java.io.InputStream |
openInputStream(android.net.Uri uri)
Open a stream to the content associated with a URI.
|
protected SafeContentResolver(android.content.Context context)
public static SafeContentResolver newInstance(android.content.Context context)
SafeContentResolver instance.context - Context used to retrieve a ContentResolver instance and the list of content providers
of this application.public java.io.InputStream openInputStream(android.net.Uri uri)
throws java.io.FileNotFoundException
If the provided URI is not a file:// URI, ContentResolver.openInputStream(Uri) is used to open a
stream. If it is a file://, this method makes sure the file isn't owned by this app.
uri - The URI pointing to the content to access.InputStream to access the content.java.io.FileNotFoundException - If the provided URI could not be opened or if it points to a file owned by this app.protected abstract int getFileUidOrThrow(java.io.FileDescriptor fileDescriptor)
throws java.io.FileNotFoundException
java.io.FileNotFoundException