The static method java.security.AccessController.doPrivileged
affirms that the invoking method assumes responsibility for enforcing its own privileges and that the access permissions of its callers should be ignored. For example, an application could have permissions to operate on a sensitive file, however, a caller of the application may be allowed to operate with only the basic permissions. Invoking doPrivileged()
in this context allows the application operating with basic permissions to use the sensitive file, for instance, when a user password change request requires an unprivileged application to use a more privileged application to set the new password.
Noncompliant Code Example
In this noncompliant code example, the doPrivileged
method is called from the openPasswordFile()
method. The openPasswordFile()
method is privileged and returns a FileInputStream
reference to its caller. This allows an untrusted caller to call openPasswordFile()
directly and obtain a reference to the sensitive file because of the inherent privileges possessed by openPasswordFile
's doPrivileged
block.
...
In general, when any method containing the doPrivileged
block exposes a field (such as a reference) beyond its own boundary, it becomes trivial for untrusted callers to exploit the program. Both of the following compliant solutions avoid exposing any reference to the privileged data.
Compliant Solution (Logging Exceptions)
The openPasswordFile()
method controls access to the sensitive password file and returns its reference. For this reason, it should not be directly invokable. Instead, the changePassword()
method must be used to forward any requests to openPasswordFile()
. This is because changePassword()
does not return a reference to the sensitive file to any caller and processes the file internally. Observe that caller supplied (tainted) inputs are not used because the name of the password file is hard-coded.
...
Code Block | ||
---|---|---|
| ||
class Password { private static void changePassword() { // Use own privilege to open the sensitive password file final String password_file = "password"; final FileInputStream f[] = {null}; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { f[0] = openPasswordFile(password_file); // call the privileged method here } catch(FileNotFoundException cnf) { // cannot recover if password file is not found; log to file } return null; } }); // Perform other operations such as old password verification } private static FileInputStream openPasswordFile(String password_file) throws FileNotFoundException { FileInputStream f = new FileInputStream(password_file); // Perform read/write operations on password file return f; } } |
Compliant Solution (Throwing Wrapped Exceptions)
The previous compliant solution logs the exception instead of revealing sensitive information. (See rule [EXC06-J. Do not allow exceptions to transmit sensitive information.) When none of the possible exceptions reveals sensitive information, we can use an equivalent mechanism that allows exceptions to be wrapped, thus providing better diagnostic information for the caller. For example, an applet that lacks read-access to system files that contain fonts can accomplish the task from a privileged block without revealing any sensitive information. When non-sensitive exceptions provide more information, the client is better able to recognize the symptoms of a read failure.
...
In summary, if the code can throw a checked exception without leaking sensitive information, prefer the form of doPrivileged
method that takes a PrivilegedExceptionAction
instead of a PrivilegedAction
.
Risk Assessment
Returning references to sensitive resources from within a doPrivileged
block can break encapsulation and confinement. Any caller who can invoke the privileged code directly and obtain a reference to a sensitive resource or field can maliciously modify its elements.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SEC02-J | medium | likely | high | P6 | L2 |
Automated Detection
Identifying sensitive information requires assistance from the programmer; fully-automated identification of sensitive information is beyond the current state of the art.
If we had user-provided tagging of sensitive information, we could do some kind of escape analysis on the doPrivileged
blocks and perhaps prove that nothing sensitive leaks out of them. We could even use something akin to thread coloring to identify the methods that either must (or must not) be called from doPrivileged
blocks.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
SCG 2007 Guideline 6-1. Safely invoke java.security.AccessController.doPrivileged
...
MITRE CWE: CWE-272 "Least Privilege Violation"
Bibliography
Wiki Markup |
---|
\[[API 2006|AA. Bibliography#API 06]\] [method doPrivileged()|http://java.sun.com/javase/6/docs/api/java/security/AccessController.html#doPrivileged(java.security.PrivilegedAction)] \[[Gong 2003|AA. Bibliography#Gong 03]\] Sections 6.4, AccessController and 9.5 Privileged Code |
...