Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading passwords with System.console()

Tags:

java

There is a Security note in the javadoc for java.io.Console class:

Security note: If an application needs to read a password or other secure data, it should use readPassword() or readPassword(String, Object...) and manually zero the returned character array after processing to minimize the lifetime of sensitive data in memory.

 Console cons;
 char[] passwd;
 if ((cons = System.console()) != null &&
     (passwd = cons.readPassword("[%s]", "Password:")) != null) {
     ...
     java.util.Arrays.fill(passwd, ' ');
 }

I do not understand why do you need such drastic measures? When the method that reads the password pops out of the stack, the array object referenced by the passwd local variable will be eligible for garbage collection. No one (even an attacker) could obtain a reference to that array, assuming that the array does not escape the method scope.

So why do you need to modify the array (erasing the password), when you know that it will be eligible for GC once the method pops out of the stack? They say:

to minimize the lifetime of sensitive data in memory

but for me this style of programming seems rather...desperate.

like image 993
Alex Avatar asked Nov 29 '22 14:11

Alex


1 Answers

Just because object is eligible for garbage collection doesn't mean that it will be garbage collected right away. And in that period of time before the garbage collection is actually executed the attacker might get a heap memory dump for instance from which they could retrieve the password.

By zeroing it out that window of opportunity is minimized.

Edit: practical experiment:

Create following Java program:

public class Main {
    private static void readPassword() {
        char[] password = System.console().readPassword();
    }

    public static void main(String[] args) throws Exception {
        readPassword();
        Thread.sleep(1000 * 3600);
    }
}
  1. javac Main.java
  2. java Main
  3. Enter password (for instance topsecret), hit enter

Next open another terminal, find out the PID of the process (let's say it's 1000) and create a heap dump using jmap:

jmap -dump:format=b,file=dump.bin 1000

Install and open VisualVM profiler, go to File/Load and select the heap dump you just created.

Next go to the OQL console and run the following query:

select a from char[] a where a.length == 9 && a[0] == 't'

As you see in the attached screenshot, array containing "topsecret" was found, even though at the point heap dump was taken there was no accessible reference to that array. So that proves that objects even if they were referenced locally stay on the heap until garbage collected.

VisualVM

Now if I were to null-out the array and try the whole procedure again, the array containing the password will not be found.

like image 83
Bohuslav Burghardt Avatar answered Dec 11 '22 04:12

Bohuslav Burghardt