Versions Compared

Key

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

Sensitive data is in memory can be vulnerable to compromise. An adversary who has control of the file system can execute code on the same system as an application may be able to access such data if the application

  • uses Uses objects to store sensitive data whose contents are not cleared or garbage-collected after use
  • has Has memory pages that can be swapped out to disk as required by the operating system (for example, to perform memory management tasks and or to support hibernation)
  • uses Holds sensitive data in a buffer to hold sensitive data (such as BufferedReader) that retains copies of the data in the OS cache or in memory
  • bases Bases its control flow on Reflection reflection that allows circumventing countermeasures to limit circumvent the limiting of the lifetime of sensitive variables
  • reveals Reveals sensitive data in debugging messages, log files, environment variables, or through thread and core dumps

Using such attacks to compromise sensitive data is far easier for live data than for data that has been cleared or reclaimed. Sensitive data that remains live beyond the minimum period required for its use has an unnecessarily large window of vulnerability. ConsequentlySensitive data leaks become more likely if the memory containing the data is not cleared after using the data. To limit the risk of exposure, programs must minimize the lifetime of sensitive data.

Currently, complete mitigation Complete mitigation (that is, foolproof protection of data in memory) requires support from the underlying operating system and Java Virtual Machine. For instanceexample, if swapping -out of sensitive data out to disk is an issue, a secure operating system that disables swapping and hibernation is indispensablerequired.

Noncompliant Code Example

This noncompliant code example reads login user name and password information from the console and stores the password as a String object object. The credentials remain exposed until the garbage collector reclaims the memory associated with the this String objects.

Code Block
bgColor#FFCCCC

class Password {
  public static void main (String args[]) throws IOException {
    Console c = System.console();
      if (c == null) {
        System.err.println("No console.");
        System.exit(1);
      }

      String loginusername = c.readLine("Enter your user name: ");
      String password = c.readLine("Enter your password: ");

      if (!verify(loginusername, password)) {
        throw new IOExceptionSecurityException("Invalid Credentials");     
      }

    //  // User is authorized, continue...
  }

  // Dummy verify method, always returns true   
  private static final boolean verify(String loginusername, String password) {
    return true;
  }
}

Compliant Solution

This compliant solution uses the Console.readPassword() method to obtain the password from the console. This method allows the password to be returned as a sequence of characters rather than as a String object. Consequently, the programmer can clear the password from the array immediately after use. The method also disables echoing of the password to the console.:

Code Block
bgColor#ccccff

class Password {
  public static void main (String args[]) throws IOException {
    Console c = System.console();
    
    if (c == null) {
      System.err.println("No console.");
      System.exit(1);
    }

    String loginusername = c.readLine("Enter your user name: ");
    char [] password = c.readPassword("Enter your password: ");
  
  boolean isValidUser if= (!verify(loginusername, password); 

    // Clear the password
    Arrays.fill(password,' ');

    if (!isValidUser) {
      throw new IOExceptionSecurityException("Invalid Credentials");     
    }
  
    // ClearUser theis password
    Arrays.fill(password, ' ');authorized, continue...
  }

  // Dummy verify method, always returns true   
  private static final boolean verify(String loginusername, char[] password) {
    return true;
  }
}

The Console.readPassword() method allows the password to be returned as a sequence of characters rather than as a String object. Because the password is never interned as a String, it will not survive garbage collection even if it matches another string. Consequently, the programmer can clear the password from the array immediately after use.

The Console.readPassword() method also disables echoing of the password to the console.

Noncompliant Code Example

This noncompliant code example uses a BufferedReader to wrap an InputStreamReader object so that sensitive data can be read from a file.:

Code Block
bgColor#FFCCCC
void readData() throws IOException {
  BufferedReader br = new BufferedReader(new InputStreamReader(
  new FileInputStream("file")));
  // Read from the file
  String data = br.readLine();
}

The BufferedReader.readLine() method returns the sensitive data as a String object, which can persist long after the data is no longer needed. The BufferedReader.read(char[], int, int) method can read and populate a char array. However, it requires the programmer to manually clear the sensitive data in the array after use. Alternatively, even if the BufferedReader were to wrap a FileReader object, it would suffer from the same pitfalls.

Compliant Solution

This compliant solution uses a direct-directly allocated NIO (new I/O) buffer to read sensitive data from the file. The data can be cleared immediately after use , and is not cached or buffered at multiple locations. It exists only in the system memory.

Code Block
bgColor#ccccff

private void readIntoDirectBufferreadData() throws IOException { {
  int bufferSize = 16 * 1024;
  byte zeroes = new byte[bufferSize];
  ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024bufferSize);
  try (FileChannel rdr = (new FileInputStream("file")).getChannel()); {
   	while (rdr.read(buffer) > 0) {

      // Do something with the buffer

	  buffer.clear();
      buffer.put(zeroes); // overwrite buffer with zeroes
	  buffer.clear();
	}
  }
 catch rdr.close();Throwable e) {
    // Handle error
  }
} 

Note that manual clearing of the buffer data is mandatory because direct buffers are exempt from not garbage collectioncollected.

Exceptions

...

Applicability

Risk Assessment

Failure to limit the lifetime of sensitive data can lead to information leaks.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

MSC10-J

medium

likely

medium

P12

L1

Related Vulnerabilities

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

Bibliography

...

...

 

...

Image Added Image Added Image Added[API 2006|AA. Bibliography#API 06]\] Class {{java.nio.ByteBuffer}} \[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID 524|http://cwe.mitre.org/data/definitions/524.html] "Information Leak Through Caching", [CWE ID 528|http://cwe.mitre.org/data/definitions/528.html] "Information Leak Through Core Dump Files", [CWE ID 215|http://cwe.mitre.org/data/definitions/215.html] "Information Leak Through Debug Information", [CWE ID 534|http://cwe.mitre.org/data/definitions/534.html] "Information Leak Through Debug Log Files", [CWE ID 526|http://cwe.mitre.org/data/definitions/526.html] "Information Leak Through Environmental Variables" and [CWE ID 226|http://cwe.mitre.org/data/definitions/226.html] "Sensitive Information Uncleared Before Release" \[[Sun 2006|AA. Bibliography#Sun 06]\] [Reading ASCII Passwords From an InputStream Example|http://java.sun.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#ReadPassword] (JCA Reference Guide) \[[Tutorials 2008|AA. Bibliography#Tutorials 08]\] [I/O from the Command Line|http://java.sun.com/docs/books/tutorial/essential/io/cl.html]MSC09-J. Carefully design interfaces before releasing them      49. Miscellaneous (MSC)      MSC11-J. Do not assume infinite heap space