Unrestricted File Download in Android
Description
In Android, content providers can abstract resources like databases or application files. Since those are fairly common scenarios, the framework provides facilities for them. Still, developers need to pay attention to what’s being exposed to the user, especially if some user-controlled value is used to identify the resource to be retrieved. In fact, a malicious user (a malicious application rather) could craft a payload that, via directory traversal (/..
), once placed into the path, targets a file outside the designated directory.
Impact
A malicious user carrying out a successful attack is able to obtain arbitrary files on the device, provided that the vulnerable application is allowed to access them.
Prevention
Care must be taken when user-controlled values are used in a sensitive context such as this one, and proper sanitization must be performed. For example, consider this ContentProvider
that’s supposed to serve files from the data directory of the application:
public class MyProvider extends ContentProvider {
// ...
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
String path = takeSomeValueFrom(uri);
final File file = new File(getContext().getFilesDir(), path);
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.parseMode(mode));
}
}
If invoked by the following URI, it could disclose files outside the legitimate directory:
content://com.example.MyProvider/../../../../../etc/hosts
A simple but effective way to prevent directory traversal is to strip everything from the user-controlled value, except for the last path fragment:
String safePath = new File(path).getName();