Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: ok big rewrite; hopefully clearer now

The static method java.security.AccessController class is part of Java's security mechanism, and it is responsible for enforcing whatever security policy is applied to code. This class's static method doPrivileged() affirms that the invoking method assumes can be used to execute a block of code while relaxing a security policy. So the block of code effectively runs with elevated privileges.

Consequently, any method that contains a doPrivileged() method call must assume 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 example, when a user password change request requires an unprivileged application to use a more privileged application to set the new passwordsecurity 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 parts.

For example, suppose a web application must maintain a sensitive file of passwords for a web service, and suppose it must run untrusted code as well. The application could then enforce a security policy preventing most of itself, including any untrusted code, from accessing the sensitive file. But since it must also provide mechanisms for adding and changing passwords, it can use the doPrivileged() method to temporarily bypass its own security policy for the purpose of managing passwords. In this case, any doPrivileged() block must prevent any information about passwords from being accessible to untrusted code.

Noncompliant Code Example

...

Code Block
bgColor#FFcccc
public class PasswordPasswordManager {

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

    // test old password with password in file contents; change password
  }

  public static FileInputStream openPasswordFile() throws FileNotFoundException {
    final String password_file = "password";

    //FileInputStream Declarefin as= finalnull;
 and assign before thetry body{
 of the anonymous inner class
 fin   // Array f[] is used to maintain language semantics while using final= AccessController.doPrivileged(
         new PrivilegedExceptionAction<FileInputStream>() {
    final FileInputStream f[] = {null};
   public // Use own privilege to open the sensitive password file
FileInputStream run() throws FileNotFoundException {
         AccessController.doPrivileged(new PrivilegedAction() {
  // Sensitive action;  public Object runcan't be done outside doPrivileged() {block
        try {
    FileInputStream      f[0] in = new FileInputStream(password_file);	//
  Perform privileged action
        } catch (FileNotFoundException cnf) {
return in;
           }
 // cannot recover if password file is not found}); log to sensitive file
    } catch (PrivilegedActionException x) {
      Exception  }cause = x.getException();
      if (cause returninstanceof null;FileNotFoundException) {
   // Still mandatory to return fromthrow run(FileNotFoundException)cause;
      } else {
        throw  }new Error("Unexpected exception type", cause); 
     return f[0]; }
  // Returns a}
 reference to privileged objects (inappropriate)
return fin;
  }
}

Compliant Solution

...

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.

This compliant solution mitigates the vulnerability by declaring openPasswordFile() to be private. Consequently, an untrusted caller can call changePassword() but cannot directly invoke openPasswordFile().

Code Block
bgColor#ccccff
public class PasswordPasswordManager {
  public static void changePassword() throws FileNotFoundException {
    // ...
  }

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

Compliant Solution (

...

Hiding Exceptions)

The previous noncompliant code example and compliant solution logs the exception instead of letting a FileNotFoundException propagate to a caller, in compliance with rule ERR01-J. Do not allow exceptions to expose sensitive information.would both throw a FileNotFoundException if the password file did not exist. But suppose that the existence of the password file is considered sensitive information, and should not be thrown to potentially untrusted code?

This compliant solution suppresses the exception, using a null return value to indicate that the file does not exist. It uses the simpler PrivilegedAction class rather than PrivilegedExceptionAction, because it does not allow any exceptions to propagate out of the doPrivileged() blockBut if none of the possible exceptions reveals sensitive information, we can use an equivalent mechanism that allows exceptions to be wrapped to provide better diagnostic information to 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.

Code Block
bgColor#ccccff
class PasswordManager {

  public static void readFont() throws FileNotFoundException changePassword() {
    FileInputStream fin = openPasswordFile();
    if (fin == null) {
      // Use own privilege to open the font file
  final String font no password file; handle error
    }

    // test old password with password in file contents; change password
  }

  private static FileInputStream openPasswordFile() {
    final String password_file = "fontfilepassword";
  try {
 final FileInputStream fin[] final= InputStream{ innull =};
    AccessController.doPrivileged( new PrivilegedExceptionAction<InputStream>PrivilegedAction() {

        public InputStreamObject run() throws FileNotFoundException {
          try {
       return openFontFile(font_file);     // call the privileged method here
 Sensitive action; can't be done outside doPrivileged() block
       }
     }fin[0] = new FileInputStream(password_file);
    //  Perform other operations
  } catch (PrivilegedActionExceptionFileNotFoundException excx) {
    Exception cause = exc.getException();
    if (cause// instanceofreport FileNotFoundException)to {handler
      throw (FileNotFoundException)cause;
    }
         } elsereturn {null;
      throw  }
  new Error("Unexpected exception type", cause});
 
   return }fin[0];
  }
}

...

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.

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5fd95d9276f01e9e-95c1bab1-45de487d-8944ab64-ea0197b29e63534a53d6f4ab"><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="c58e4027d8754822-373125c6-48144aae-b2fb9731-f5815624869f4c609d517d85"><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>

...