views:

201

answers:

5

We know it's a good practice to prefer char[] over java.lang.String to store passwords. That's for the following two reasons (as I have read):

  1. char[] are mutable so we can clear the passwords after the usage.
  2. String literals goes to a pool that will not get garbage collected as other objects, hence might appear in memory dumps.

But java.sql.DriverManager doesn't have a getConnection() that comply with the above best practice because its password parameter is String.

DriverManager.getConnection(String url, String user, String password)

I think the API should have an overloaded method with the following signature:

DriverManager.getConnection(String url, String user, char[] password)

What do you think about this? Do you see any alternative way to overcome this draw back?

Would love to hear your thoughts.

+4  A: 

String literals go in a pool, but I wouldn't expect the password to be a literal (hardcoded in the program). I would expect it to come from a configuration or similar. As such it won't be a literal and will get garbage collected (provided all references are binned).

Brian Agnew
+1  A: 

One can only speculate, unless you can ask the designer of the API.

My speculation is this:

The main API that uses char[] instead of String for passwords that I know of is JPasswordField. It does so in order to allow the program to overwrite the user-entered password with other values once the values have been used (which is not possible with a String, which will linger in memory at least until it is garbage-collected).

The password used to connect to a database is usually not user-entered in most applications I know, but comes from some kind of configuration/directory/...

Not matter where it comes from: the application is able to re-construct it once it is no longer known. This is the big difference between user-entered passwords and programmatically acquired passwords.

Since the password usually can be acquired on easier ways than to search through all the memory a program has used, fixing this attack vector is not a high priority

</speculation>

Joachim Sauer
+1  A: 

Your reason #2 is the one I've seen given most commonly for use of char[] over String. However, in general I think that if you assume that someone has access to your program state via a debugger or other means, there's no reason they can't also look at the contents of a char[].

Alex Miller
+1  A: 

The argument to use char[] arrays applies most where the user types the password, and you want to minimize the exposure of that password.

JDBC connections are almost never like that. The password is stored in some configuration file, perhaps obfuscated, and is a much bigger source of a leak than the potential to read memory.

Anyway, the JDBC standard allows for passing passwords in properties objects and even in the URL, so I think having a char[] password parameter would give you a false sense of security.

If you have a real use case where the password needs to be removed from memory as quickly as possible to be unrecoverable, and that otherwise makes sense in the context of a real JDBC application, I would love to hear it. I can imagine that such a thing could exist, but I can't think of a scenario where the use of a char[] really makes things more secure.

Yishai
+1  A: 

Your point 1 is valid to some extend, but point 2 about Strings ending up in a uncollected string pool is only true for static literal strings (strings that appear directly in the code). If you would have passwords stored directly in your code I'd recommend to worry about these first as it is far easier to find them in classfiles then in a running VM.

So if you think you must store your passwords in a char[] you can still create a String object from it before you call getConnection(). If the driver implementation doesn't store the string object internally it will quickly not be reachable anymore and thus get collected pretty fast. The only chance to still read it back then is to examine the memory of the JVM directly where it still might exist. So you are right that using a char[] would be a bit more secure but not much as the password would have to be in the memory at the some point anyway.

I.e. a very simple way to grab the password with any kind of API would be to inject a faked SQL driver and to grab the password directly in the connect method. Whoever is able to examine the JVM memory to find a not yet overwritten password string in it will also be able to do inject a modified driver jar.

x4u
Excellent point about how the pluggable nature of JDBC makes it quite easy to replace a driver to a database with your own.
Yishai