Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I ensure the destruction of a String object in Java?

Tags:

java

security

An empoyee at my company needs to modify data from a SQL Server database through a program I made. The program used Windows authentication at first, and I asked the DBAs to give this specific user write access to said database.

They were not willing to do this, and instead gave write access to my Windows user account.

Since I trust the guy but not enough to let him work 90 minutes with my session open, I'll just add a login prompt to my program, asking for a username and password combination, and log in to SQL Server with it. I'll log in, and trust my application to let him do only what he needs to.

This, however, raises a small security risk. The password fields tutorial over SunOracle's site states that passwords should be kept the minimum amount of time required in memory, and to this end, the getPassword method returns a char[] array that you can zero once you're done with it.

However, Java's DriverManager class only accepts String objects as passwords, so I won't be able to dispose of the password as soon as I'm done with it. And since my application is incidentally pretty low on allocations and memory requirements, who knows how long it'll survive in memory? The program will run for a rather long time, as stated above.

Of course, I can't control whatever the SQL Server JDBC classes do with my password, but I hoped I could control what I do with my password.

Is there a surefire way to destroy/zero out a String object with Java? I know both are kind of against the language (object destruction is non-deterministic, and String objects are immutable), and System.gc() is kind of unpredictable too, but still; any idea?

like image 425
zneak Avatar asked Mar 08 '11 20:03

zneak


People also ask

How do you destruct an object in Java?

Just before destroying an object, Garbage Collector calls finalize() method on the object to perform cleanup activities. Once finalize() method completes, Garbage Collector destroys that object.

Can we destroy objects in Java?

Java doesn't let you destroy objects. Any unreachable object may (or may not) be GCed at any particular point in time.

How can a program destroy an object it has created?

Question: How does a program destroy an object that it creates? Answer: A program does not explicitly destroy objects. A program can set all references to an object to null so that it becomes eligible for garbage collection. But the program does not actually destroy objects.

Which of the following option destroys an object reference obj in a Java program?

Only the garbage collection system can destroy an object. Explanation: Option D is correct. When an object is no longer referenced, it may be reclaimed by the garbage collector.


2 Answers

So, here's the bad news. i'm surprised no one has mentioned it yet. with modern garbage collectors, even the whole char[] concept is broken. regardless of whether you use a String or a char[], the data can end up living in memory for who-knows-how-long. why is that? because modern jvms use generational garbage collectors which, in short, copy objects all over the place. so, even if you use a char[], the actual memory it uses could get copied to various locations in the heap, leaving copies of the password everywhere it goes (and no performant gc is going to zero out old memory). so, when you zero out the instance you have at the end, you are only zeroing out the latest version in memory.

long story, short, there's no bulletproof way to handle it. you pretty much have to trust the person.

like image 65
jtahlborn Avatar answered Sep 30 '22 11:09

jtahlborn


I can only think of a solution using reflection. You can use reflection to invoke the private constructor that uses a shared character array:

  char[] chars = {'a', 'b', 'c'};   Constructor<String> con = String.class.getDeclaredConstructor(int.class, int.class, char[].class);   con.setAccessible(true);   String password = con.newInstance(0, chars.length, chars);   System.out.println(password);    //erase it   Arrays.fill(chars, '\0');   System.out.println(password); 

Edit

For anyone thinking this is a failproof or even useful precaution, I encourage you to read jtahlborn's answer for at least one caveat.

like image 23
Mark Peters Avatar answered Sep 30 '22 11:09

Mark Peters