Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The java.security.AccessController class is part of Java's security mechanism; it is responsible for enforcing whatever the applicable security policy is applied to code. This class's static method doPrivileged() can be used to execute a block of code while relaxing a security policy. So the block of code effectively runs with elevated privileges method executes a code block with a relaxed security policy. The doPrivileged() method stops permissions from being checked further down the call chain.

Consequently, any method that contains a invokes doPrivileged() method call must assume responsibility for enforcing its own security on the code block supplied to doPrivileged(). Likewise any , code in the {[doPrivileged()}} method must take care to prevent sensitive information from leaking out of a trust boundary. This may indicate that said information must not escape from the doPrivileged() block itself, or it may be permitted within part of the application and excluded from other partsnot leak sensitive information or capabilities.

For example, suppose that a web application must maintain a sensitive password file of passwords for a web service , and further that it also must also run untrusted code. The application could then enforce a security policy preventing the majority of its own code, and code—as well as all untrusted code, from code—from accessing the sensitive file. Because it must also provide mechanisms for adding and changing passwords, it can use call the doPrivileged() method to temporarily bypass its own security policy for the purpose of managing passwordsallow untrusted code to access the sensitive file. In this case, any privileged block must prevent any all information about passwords from being accessible to untrusted code.

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 for the sensitive password file to its caller. Because the method is public, it could be invoked by an untrusted caller.

Code Block
bgColor#FFcccc

public class PasswordManager {

  public static void changePassword() throws FileNotFoundException {
    FileInputStream fin = openPasswordFile();

    // testTest 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;
  }
}

Compliant Solution

In general, when any method containing a privileged block exposes a field (such as a an object reference) beyond its own boundary, it becomes trivial for untrusted callers to exploit the program. 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
bgColor#ccccff

public class PasswordManager {
  public static void changePassword() throws FileNotFoundException {
    // ...
  }

  private static FileInputStream openPasswordFile() 
     throws FileNotFoundException {
    // ...
  }
}

Compliant Solution (Hiding Exceptions)

Both the The previous noncompliant code example and the previous compliant solution would throw a FileNotFoundException when the password file is missing. But suppose that If the existence of the password file is itself considered sensitive information, and should not be revealed to potentially untrusted code?this exception also must be prevented from leaking outside the trusted code.

This compliant solution suppresses the exception, using leaving the array to contain a single null return 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
bgColor#ccccff

class PasswordManager {

  public static void changePassword() {
    FileInputStream fin = openPasswordFile();
    if (fin == null) {
      // noNo password file; handle error
    }

    // testTest 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 PrivilegedActionPrivilegedAction<Void>() {
        public ObjectVoid run() {
          try {
            // Sensitive action; can't be done outside
            // doPrivileged() block
            fin[0] = new FileInputStream(password_file);
          } catch (FileNotFoundException x) {
            // reportReport to handler
          }
          return null;
        }
      });
    return fin[0];
  }
}

Risk Assessment

Returning references to sensitive resources from within a doPrivileged() block can break encapsulation and confinement and can leak capabilities. 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 Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SEC00-J

medium Medium

likely Likely

high 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 Assuming user-provided tagging of sensitive information, we could do some kind of escape analysis could be performed on the doPrivileged() blocks and perhaps to prove that nothing sensitive leaks out of from them. We could even use something akin to thread coloring Methods similar to those used in thread-role analysis could be used to identify the methods that either must (, or must not) , be called from doPrivileged() blocks.

Related Guidelines

MITRE CWE

CWE-266, " Incorrect Privilege Assignment"

 

CWE-272, " Least Privilege Violation"

Secure Coding Guidelines for the Java Programming LanguageSE, Version 35.0

Guideline 6-2 9-3 / ACCESS-3: Safely invoke java.security.AccessController.doPrivileged()

Bibliography

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="dc55ce05-1f15-4540-b7e0-32f5f9d7069e"><ac:plain-text-body><![CDATA[

[[API 2006

AA. Bibliography#API 06]]

[method doPrivileged()

http://java.sun.com/javase/6/docs/api/java/security/AccessController.html#doPrivileged(java.security.PrivilegedAction)]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="14d64764-3b30-4844-8387-16e5cc81b645"><ac:plain-text-body><![CDATA[

[[Gong 2003

AA. Bibliography#Gong 03]]

Sections 6.4, AccessController and 9.5 Privileged Code

]]></ac:plain-text-body></ac:structured-macro>

Android Implementation Details

The java.security package exists on Android for compatibility purposes only, and it should not be used.

Bibliography

[API 2014]

Method doPrivileged()

[Gong 2003]

Section 6.4, "AccessController"
Section 9.5, "Privileged Code"

 

...

Image Added Image Added 14. Platform Security (SEC)      14. Platform Security (SEC)