...
- Uses objects to store sensitive data whose contents are not cleared or garbage-collected after use.
- Has memory pages that can be swapped out to disk as required by the operating system (for example, to perform memory management tasks or to support hibernation).
- Holds sensitive data in a buffer (such as
BufferedReader
) that retains copies of the data in the OS cache or in memory. - Bases its control flow on reflection that allows circumventing countermeasures to limit the lifetime of sensitive variables.
- Reveals sensitive data in debugging messages, log files, environment variables, or through thread and core dumps.
Using such attacks to compromise sensitive data becomes harder Sensitive data leaks become more likely if the memory containing the data has been cleared. Sensitive data that remains live beyond the minimum period required for its use has an unnecessarily large window of vulnerability. Consequentlyis not cleared after using the data. To limit the risk of exposure, programs must minimize the lifetime of sensitive data.
Currently, complete Complete mitigation (that is, complete foolproof protection of data in memory) requires support from the underlying operating system and Java Virtual Machine. For instanceexample, if swapping sensitive data out to disk is an issue, a secure operating system that disables swapping and hibernation is required.
...
This noncompliant code example reads login user name and password information from the console and stores the password as a String
object. The credentials remain exposed until the garbage collector reclaims the memory associated with the this String
.
Code Block | ||
---|---|---|
| ||
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 SecurityException("Invalid Credentials"); } // ... } // Dummy verify method, always returns true private static final boolean verify(String loginusername, String password) { return true; } } |
...
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 | ||
---|---|---|
| ||
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: "); if (!verify(loginusername, password)) { throw new SecurityException("Invalid Credentials"); } // Clear the password Arrays.fill(password, ' '); } // Dummy verify method, always returns true private static final boolean verify(String login, 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. Consequently, the programmer can clear the password from the array immediately after use. This method also disables echoing of the password to the console.
Noncompliant Code Example
...
Code Block | ||
---|---|---|
| ||
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 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.
...
Note that manual clearing of the buffer data is mandatory because direct buffers are exempt from not garbage collectioncollected.
Applicability
Failure to limit the lifetime of sensitive data can lead to information leaks.
This rule may be violated when both of the following are true:
- It can be proved that the code is free from other errors that can expose the sensitive data.
- Attackers lack physical access to the target machine.
Bibliography
[API 20112013] | Class ByteBuffer |
[Oracle 2012b] | Reading ASCII Passwords from an InputStream Example (Java Cryptography Architecture [JCA] Reference Guide) |
[Tutorials 2008] | I/O from the Command Line |
...