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 the applicable security policy. This class's static doPrivileged() method doPrivileged is used to affirm that the invoking method is taking responsibility for exercising its own permissions and that the access permissions of its callers should be ignored. For example, an application may have permissions to operate on a sensitive file, however, a caller of this application may be allowed to operate with only basic user permissions. Invoking doPrivileged() in the context of this method allows it to exercise its own (possibly elevated) permissions under such circumstances.

Noncompliant Code Example

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 invokes doPrivileged() must assume responsibility for enforcing its own security on the code block supplied to doPrivileged(). Likewise, code in the doPrivileged() method must not leak sensitive information or capabilities.

For example, suppose that a web application must maintain a sensitive password file for a web service and also must 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 call the doPrivileged() method to temporarily allow untrusted code to access the sensitive file. In this case, any privileged block must prevent 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. Because the method is public, it could be invoked by an untrusted callerThere are two fallacies in this noncompliant code example. First, the doPrivileged method is being called from inside the openPasswordFile method. The openPasswordFile method is privileged and returns a FileInputStream reference to its caller. This allows any caller to call openPasswordFile() directly and obtain a reference to the sensitive file due to the inherent privileges present within the corresponding code. Second, the name of the sensitive password file is user controllable which introduces other risks such as unaccounted misuse of miscellaneous sensitive files.

Code Block
bgColor#FFcccc

public class PasswordPasswordManager {

 
 public static void changePassword(String password_file) throws FileNotFoundException {
    FileInputStream fin;
    fin = openPasswordFile(password_file);
 }
	
 public static FileInputStream openPasswordFile(String password_file) throws FileNotFoundException {
    //Declare asTest finalold andpassword assignwith beforepassword thein bodyfile ofcontents; the anonymous inner classchange password,
    //Array f[] is used to maintain language semantics while using final  then close the password file
  }

  public static FileInputStream openPasswordFile()
    final  throws FileInputStreamFileNotFoundException f[]={null};
    final String password_file =  "password_file";
    //UseFileInputStream ownfin privilege= tonull;
 open the sensitive passwordtry file{
      fin = AccessController.doPrivileged(
        new PrivilegedActionPrivilegedExceptionAction<FileInputStream>() {
          public ObjectFileInputStream run() throws FileNotFoundException {
   
         // Sensitive action; can't be done outside tryprivileged {block
            f[0]FileInputStream in = new FileInputStream("c:\\" + file);	//Perform privileged actionpassword_file);
            return in;
          }
      });
    } catch (FileNotFoundExceptionPrivilegedActionException cnfx) { System.err.println(cnf.getMessage()); }

      Exception cause = x.getException();
       return null;if (cause instanceof 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 a privileged block exposes a field (such as 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)

The previous noncompliant code example and the previous compliant solution throw a FileNotFoundException when the password file is missing. If the existence of the password file is itself considered sensitive information, this exception also must be prevented from leaking outside the trusted code.

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 valueThe openPasswordFile method controls access to the sensitive password file and returns its reference. Since it cannot control being invoked by untrusted user methods, it should not assert its privileges within the body. Instead, changePassword() the caller method, can safely assert its own privilege whenever someone else calls it. This is because changePassword() does not return a reference to the sensitive file to any caller but processes the file internally. Also, since the name of the password file is hard-coded in the code, caller supplied (tainted) inputs are not used.

Code Block
bgColor#ccccff

class PasswordPasswordManager {

  public static void changePassword() {
    FileInputStream fin = openPasswordFile();
    if (fin == null) {
      //Use own privilege to open the sensitive password file
   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 ffin[] = { null };
    AccessController.doPrivileged(new PrivilegedActionPrivilegedAction<Void>() {
        public ObjectVoid run() {
          try {
             f// Sensitive action; can't be done outside
            // doPrivileged() block
            fin[0] = new openPasswordFileFileInputStream(password_file);
  //call  the privileged method here
   } catch (FileNotFoundException cnfx) { System.err.println("Error: Operation could not be performed"); }

           return null;
// Report to }handler
  });
 //Perform other operations such as password verification
 }	

    public static FileInputStream openPasswordFile(String password_file) throws FileNotFoundExceptionreturn {null;
  FileInputStream f = new FileInputStream("c:\\" + password_file);}
  //Perform read/write operations on});
 password file
  return ffin[0];
  }
}

Risk Assessment

Invoking doPrivileged with too large a scope may seriously compromise the security of a Java applicationReturning 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.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SEC01SEC00-J

medium Medium

probable Likely

high High

P4 P6

L3 L2

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Identifying sensitive information requires assistance from the programmer; fully automated identification of sensitive information is beyond the current state of the art.

Assuming user-provided tagging of sensitive information, escape analysis could be performed on the doPrivileged() blocks to prove that nothing sensitive leaks out 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.

Related Guidelines

MITRE CWE

CWE-266, Incorrect Privilege Assignment
CWE-272, Least Privilege Violation

Secure Coding Guidelines for Java SE, Version 5.0

Guideline 9-3 / ACCESS-3: Safely invoke java.security.AccessController.doPrivileged

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 Image Added Wiki Markup\[[Gong 03|AA. Java References#Gong 03]\] 6.4 AccessController \[[SCG 07|AA. Java References#SCG 07]\] Guideline 6-1 Safely invoke java.security.AccessController.doPrivileged \[[API 06|AA. Java References#API 06]\] [doPrivileged method|http://java.sun.com/javase/6/docs/api/java/security/AccessController.html#doPrivileged(java.security.PrivilegedAction)]