...
- uses objects to store sensitive data whose values 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 (to perform memory management tasks and to support hibernation)
- uses any buffers to hold sensitive data (such as
BufferedReader
). The OS cache and in the in-memory copy of the data are also retained in this case. - bases its control flow on Reflection that circumvents allows circumventing any countermeasures to limit the lifetime of sensitive variables
- reveals sensitive data in debugging messages, log files, environment variables or through thread dumps and core dumps
...
This noncompliant code example reads login information from the console and stores the password as a String
object. Consequently, the password credentials may remain exposed until the garbage collector reclaims the memory associated with the object String
objects.
Code Block |
---|
|
class BadPassword {
public static void main (String args[]) throws IOException {
Console c = System.console();
if (c == null) {
System.err.println("No console.");
System.exit(1);
}
String login = c.readLine("Enter your user name: ");
String password = c.readLine("Enter your password: ");
if (!verify(login, password)) {
throw new IOException("Invalid Credentials");
}
// ...
}
// dummyDummy verify method, always returns true
private static final boolean verify(String login, String password) {
return true;
}
}
|
...
Code Block |
---|
|
class GoodPassword {
public static void main (String args[]) throws IOException {
Console c = System.console();
if (c == null) {
System.err.println("No console.");
System.exit(1);
}
String login = c.readLine("Enter your user name: ");
char [] password = c.readPassword("Enter your password: ");
if (!verify(login, password)) {
throw new IOException("Invalid Credentials");
}
// ... Clear the password
Arrays.fill(password, ' ');
}
// dummyDummy verify method, always returns true
private static final boolean verify(String login, char[] password) {
return true;
}
}
|
...
Code Block |
---|
|
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream("file")));
// readRead from the file
|
Compliant Solution
This compliant solution uses a direct allocated NIO buffer to read sensitive data from the file. The data can be cleared immediately after use and is not cached or buffered in at multiple locations. It exists only in the system memory.
Code Block |
---|
|
private void readIntoDirectBuffer() throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(16*1024);
FileChannel rdr = (new FileInputStream("file")).getChannel();
while(rdr.read(buffer) > 0) {
// doDo something with the buffer
buffer.clear();
}
rdr.close();
}
|
...