You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 58 Next »

The static method java.security.AccessController.doPrivileged is used to affirm that the invoking method is taking responsibility for enforcing its own privileges 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 the application may be allowed to operate with only the very basic permissions. Invoking doPrivileged() in this context allows the application operating with only 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 the corresponding code.

public class Password { 
  public static void changePassword(final String password_file) throws FileNotFoundException {
    FileInputStream fin;
    fin = openPasswordFile(password_file);
  }
	
  public static FileInputStream openPasswordFile(String password_file) throws FileNotFoundException {
    // Declare as final and assign before the body of the anonymous inner class
    // Array f[] is used to maintain language semantics while using final 
    final FileInputStream f[] = {null};
    // Use own privilege to open the sensitive password file
    AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {   
        try {
          f[0] = new FileInputStream(password_file);	//Perform privileged action
        } catch(FileNotFoundException cnf) { 
          // cannot recover if password file is not found; log to file 
        }
        return null;    //Still mandatory to return from run()
      }
    });
   return f[0];  //Returns a reference to privileged objects (inappropriate)
 }	
}

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.

Compliant Solution

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.

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

The previous compliant solution logs the exception instead of revealing sensitive information. (See guideline EXC06-J. Do not allow exceptions to transmit sensitive information for more information.) Sometimes no sensitive information can be revealed by any of the possible exceptions. In such cases, an equivalent mechanism that allows exceptions to be wrapped can be used. This allows the caller to obtain better diagnostic information. For example, if an applet doesn't have access to read system files that contain fonts, it can accomplish the task from a privileged block without revealing any sensitive information. In fact, if non-sensitive exceptions provide more information, the client can deduce the symptoms of a read failure more easily.

public static void readFont() throws FileNotFoundException {
  // Use own privilege to open the font file
  final String font_file = "fontfile";
  try {
    final InputStream in =
    AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>() {
				  
     public InputStream run() throws FileNotFoundException {
       return openFontFile(font_file); //call the privileged method here
     }
    });
    // Perform other operations 
  } catch (PrivilegedActionException exc) {				
      Exception cause = exc.getException();
      if (cause instanceof FileNotFoundException) {
        throw (FileNotFoundException)cause;
      } else { throw new Error("Unexpected exception type", cause); }
    }			
}

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

TODO

Related Vulnerabilities

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

References

[[API 2006]] method doPrivileged()
[[Gong 2003]] Sections 6.4, AccessController and 9.5 Privileged Code
[[SCG 2007]] Guideline 6-1 Safely invoke java.security.AccessController.doPrivileged
[[MITRE 2009]] CWE ID 266 "Incorrect Privilege Assignment", CWE ID 272 "Least Privilege Violation"


SEC01-J. Minimize the accessibility of classes and their members      02. Platform Security (SEC)      SEC03-J. Do not allow tainted variables in doPrivileged blocks

  • No labels