Unix-style file permissions are present in Android
for file systems that are formatted to support them, such as the root
file system. Each application has its own area on the file system that
it owns, almost like programs have a home directory to go along with
their user IDs. An Activity or Service’s Context object gives access to
this directory with the getFilesDir(), getDir(), openFileOutput(),
openFileInput(), and getFileStreamPath() methods, but the files and
paths returned by the context are not special and can be used with
other file-management objects such as FileInputStream. The mode
parameter is used to create a file with a given set of file permissions
(corresponding to the Unix file permissions). You can bitwise-OR these
permissions together. For example, a mode of MODE_WORLD_WRITABLE |
MODE_WORLD_READABLE makes a file world-readable and writable. (World is
also known as “other,” so MODE_WORLD_WRITEABLE creates other writeable
files, like the command chmod o+w somefile does.) The value
MODE_PRIVATE cannot be combined this way because it is just a zero.
Somewhat oddly, the mode parameter also indicates if the resultant file
is truncated or opened for appending with MODE_APPEND.
The following code is a simple example of creating a sample file that can be read by anyone:
fos = openFileOutput("PublicKey", Context.MODE_WORLD_READABLE);
The
resultant FileOutputStream (called “fos” in this example) can be
written to only by this process, but it can be read by any program on
the system.
This interface of passing in
flags that indicate whether files are world-readable or world-writable
is simpler than the file permissions Linux supports, but should be
sufficient for most applications. To experiment with full Linux file
permissions, you could try executing chmod, or the “less documented”
android.os.FileUtils class’s static method setPermissions(), which
takes a filename and a mode uid and gid. Generally, any code that
creates data that is world-accessible must be carefully reviewed to
consider the following:
Is anything written to this file sensitive? For example, something only you know because of a permission you have.
Could a change to this data cause something unpleasant or unexpected to happen?
Is
the data in a complex format whose native parser might have exploitable
vulnerabilities? Historically a lot of complex file format parsers
written in C or C++ have had exploitable parser bugs.
If
the file is world-writeable, a bad program could fill up the phone’s
memory and your application would get the blame! This kind of
antisocial behavior might happen—and because the file is stored under
your application’s home directory, the user might choose to fix the
problem by uninstalling your program or wiping its data.
Obviously,
executable code such as scripts, libraries, and configuration files
that specify which components, sites, or folders to use would be bad
candidates for allowing writes. Log files, databases, and pending work
would be bad candidates for world-readability.
SharedPreferences is a
system feature that is backed by a file with permissions like any
others. The mode parameter for getSharedPreferences(String name, int
mode) uses the same file modes defined by Context. It is very unlikely
you have preferences so unimportant you don’t mind if other programs
change them. I recommend avoiding using MODE_WORLD_WRITEABLE and
suggest searching for it when reviewing an application as an obvious
place to start looking for weaknesses.