...
In this noncompliant code example, the doPrivileged()
method is called from the openPasswordFile()
method. The openPasswordFile()
method is privileged and returns a FileInputStream
for the sensitive password file. Because the method is public, it could be invoked by an untrusted caller.
Code Block | ||
---|---|---|
| ||
public class PasswordManager {
public static void changePassword() throws FileNotFoundException {
FileInputStream fin = openPasswordFile();
// test old password with password in file contents; change password
// then close the password file
}
public static FileInputStream openPasswordFile()
throws FileNotFoundException {
final String password_file = "password";
FileInputStream fin = null;
try {
fin = AccessController.doPrivileged(
new PrivilegedExceptionAction<FileInputStream>() {
public FileInputStream run() throws FileNotFoundException {
// Sensitive action; can't be done outside privileged block
FileInputStream in = new FileInputStream(password_file);
return in;
}
});
} catch (PrivilegedActionException x) {
Exception cause = x.getException();
if (cause instanceof FileNotFoundException) {
throw (FileNotFoundException) cause;
} else {
throw new Error("Unexpected exception type", cause);
}
}
return fin;
}
}
|
...
This compliant solution mitigates the vulnerability by declaring openPasswordFile()
to be private. Consequently, an untrusted caller can call changePassword()
but cannot directly invoke the openPasswordFile()
method.
Code Block | ||
---|---|---|
| ||
public class PasswordManager {
public static void changePassword() throws FileNotFoundException {
// ...
}
private static FileInputStream openPasswordFile()
throws FileNotFoundException {
// ...
}
}
|
...
This compliant solution suppresses the exception, leaving the array to contain a single null value to indicate that the file does not exist. It uses the simpler PrivilegedAction
class rather than PrivilegedExceptionAction
to prevent exceptions from propagating out of the doPrivileged()
block. The Void
return type is recommended for privileged actions that do not return any value.
Code Block | ||
---|---|---|
| ||
class PasswordManager {
public static void changePassword() {
FileInputStream fin = openPasswordFile();
if (fin == null) {
// no password file; handle error
}
// test old password with password in file contents; change password
}
private static FileInputStream openPasswordFile() {
final String password_file = "password";
final FileInputStream fin[] = { null };
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
try {
// Sensitive action; can't be done outside
// doPrivileged() block
fin[0] = new FileInputStream(password_file);
} catch (FileNotFoundException x) {
// report to handler
}
return null;
}
});
return fin[0];
}
}
|
...
CWE-266. Incorrect privilege assignment | |
| CWE-272. Least privilege violation |
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 6-2. Safely invoke |
Android Implementation Details
The java.security
package exists on Android for compatibility purposes only and it should not be used.
Bibliography
[API 2006] | |
Sections 6.4, |