Versions Compared

Key

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

...

For example, suppose that a web application must maintain a sensitive password file for a web service and also run untrusted code. The application could then enforce a security policy preventing the majority of its own code – as well as all untrusted 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 allow untrusted code to access the sensitive file. In this case, any privileged block must prevent any information about passwords from being accessible to untrusted code.

...

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();

    // 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
bgColor#ccccff
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 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) {
      // 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];
  }
}

...

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.

...

Assuming user-provided tagging of sensitive information, escape analysis could be performed on the doPrivileged() blocks and to prove that nothing sensitive leaks out of from them. Methods similar to those used in thread-role analysis could be used to identify the methods that must, or must not, be called from doPrivileged() blocks.

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="3aec41c83adf3d0d-4a97b021-4e694313-b815bcd3-95ab28de23ff2bbb175bbed6"><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="faf7c5204971baa4-b36c6fa8-44064f23-90009cae-b5b2e36b35bf437006fde401"><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>

...