Sensitive data in memory can be vulnerable to compromise. An adversary who can execute code on the same system as an application may be able to access such data if the application
- 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 countermeasures to circumvent the limiting of the lifetime of sensitive variables
- Reveals sensitive data in debugging messages, log files, environment variables, or through thread and core dumps
Sensitive 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.
Complete mitigation (that is, foolproof protection of data in memory) requires support from the underlying operating system and Java Virtual Machine. For example, if swapping sensitive data out to disk is an issue, a secure operating system that disables swapping and hibernation is required.
Noncompliant Code Example
This noncompliant code example reads 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 this
This compliant solution uses the
Console.readPassword() method to obtain the password from the console:
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.
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:
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.
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 not garbage collected.
Failure to limit the lifetime of sensitive data can lead to information leaks.
|[API 2013]||Class |
|[Oracle 2013b]||Reading ASCII Passwords from an |
|[Tutorials 2013]||I/O from the Command Line|