7

As the title says, I'm looking into finding a way to use a char[] array to establish a JDBC connection instead of creating a new String object from the char[] array and using that to establish the connection.

Because char[] arrays are more secure than Strings in java, I've been wanting to keep things as secure as possible when dealing with my JPasswordFields.

In this particular case, I'm taking the char[] array contents of a JPasswordField and attempting to establish a JDBC connection to a database. It works perfectly well, but I'm having to create a new String object from the char[] array to actually call the getConnection method.

Is there any way to ensure at-least some security doing this, or am I just forced to create the String object and continue on using that in the method?

This is my code:

/**
 * Construct a new DataManager object with it's own
 * connection to the database.
 *
 * @param ipAddress The IP address to the server on which MySQL is running.
 * @param port The port to use when connecting to MySQL.
 * @param databaseName The database name of the database to connect to.
 * @param username The username for a MySQL account with access to the specified database.
 * @param password The password for the MySQL account specified by the specified username.
 */
public DataManager(final String ipAddress, final String port, final String databaseName, final String username, final char[] password) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
    Class.forName("com.mysql.jdbc.Driver").newInstance();
    String url = "jdbc:mysql://" + ipAddress + ":" + port + "/" + databaseName + "?noAccessToProcedureBodies=true"; //?noAccessToProcedureBodies=true is required for using the stored procedures.
    dbConnection = DriverManager.getConnection(url, username, new String(password));
}

Sorry for the formatting, but the lines are a bit long and they wrap.

Here's the Java docs for the DriverManager class that I'm using. I've checked and there doesn't seem to be a method to use the char[] instead of the String and that's what prompted this post.

Thanks for any help/tips.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • 1
    Related: [String or char array for password when using JDBC?](http://stackoverflow.com/questions/20342389/string-or-char-for-password-when-using-jdbc) – Pshemo Jul 07 '15 at 23:04
  • 1
    Perhaps you want a codereview of end-to-end so you can learn where the security holes exist – Drew Jul 07 '15 at 23:05
  • @Pshemo After a quick readthrough of that link, it seems like they're mostly just discussing why you shouldn't store a password as a String and instead use a char[] array. There is one suggestion to use a connection pool/manager and then allow only it to access the password, but that would still mean that the password is kept around to be reused, doesn't it? –  Jul 07 '15 at 23:08
  • @DrewPierce That might be pretty useful in the future, but I'm specifically looking for the most secure way to connect to the database with the password being stored as a char[] array instead of a String at the moment. The only other code dealing with the password other than the snippet in the OP just pulls the password as a char[] array from the JPasswordField during a call to the method in the OP. –  Jul 07 '15 at 23:10
  • 1
    I didn't post this link as candidate of duplicate of your question with proper answer, but as resource of some additional informations. – Pshemo Jul 07 '15 at 23:11
  • @Pshemo =P I figured that's why you posted it. It did offer some additional information and I'm currently looking into the manager/pool. Thanks. –  Jul 07 '15 at 23:14
  • You're not the first person to discover that this advice is incompatible with many commons APIs, including [HTTP servlets](https://stackoverflow.com/questions/15016250/in-java-how-do-i-extract-a-password-from-a-httpservletrequest-header-without-ge). Not that you asked, but it smacks of security theatre to me: probably not on the top 1000 list of common security issues, more like developer navel-gazing. – DavidS Jul 07 '15 at 23:14
  • A `String` is a wrapper for a `char[]` If the API expect a `String` that is what you must use, but if you need to clear the `char[]` after it has been used, there is nothing to stop you doing so, though you might need to use reflection to access the `char[]`. – Peter Lawrey Jul 07 '15 at 23:32
  • No one suggested that at the [link he posted](https://stackoverflow.com/questions/8881291/why-is-char-preferred-over-string-for-passwords), @PeterLawrey. Either what you're suggesting isn't possible, or you could post a valuable new answer at that link. – DavidS Jul 07 '15 at 23:46
  • @DavidS It'd be pretty nice if they started depreciating everything that should require a bit more security and create new methods/API that support using a char[] array. It doesn't make too much sense as to why they don't already to me. –  Jul 08 '15 at 01:24
  • 4
    In my uneducated opinion, it's because they deem the security risk too trivial to warrant the effort. That char[] is "more secure" than String seems more like Java trivia than useful security advice. If an attacker is taking memory dumps of your application, (1) you've got more serious problems and (2) the dumps will likely include the confidential data the password is meant to protect. – DavidS Jul 08 '15 at 04:47
  • @DavidS I see your point. It definitely does seem pretty trivial now that I reflect on what I've read. It's a nice _slight_ security increase, but I can assume that it would take quite a while to rewrite and redesign a fair amount of code just to support char[] instead of String. –  Jul 08 '15 at 05:35
  • 2
    @DavidS As Jon states "there's no way (aside from reflection)" I am suggesting you could use reflection if used with care. – Peter Lawrey Jul 08 '15 at 09:20
  • 2
    @DavidS I have added an answer on how to use reflection to so this https://stackoverflow.com/questions/8881291/why-is-char-preferred-over-string-for-passwords/31288609#31288609 note: anywhere you have kept a copy of the reference to the password will also be clobbered, for better or worse. – Peter Lawrey Jul 08 '15 at 09:28
  • 1
    @PeterLawrey Thanks for the link. I've never actually known what reflection was until I read through both that and another question on this site. It's actually pretty interesting. –  Jul 08 '15 at 16:23

1 Answers1

4

As @DavidS said in the comments, I'm not sure using a char[] is really more secure in a meaningful way, but I did dig into the the DriverManager source to see if it was possible to use anyway.

If you look at the getConnection() method you're using you'll see that it (along with the other parameter variations) is collecting all the provided connection information in a java.util.Properties, which is essentially a String->String hash table. The Properties object is then passed to the needed driver on a method that's defined as part of the long standing (and thus very unlikely to change) java.sql.Driver interface, with any implementation of that obviously dependent on the driver.

At that point I think you have to automatically assume that someone somewhere will either make a copy of the supplied password String or include it in the composition of a bigger String, and so you can't rely on reflection to go back and clear out that buffer. For example, in the PostgreSQL JDBC driver, depending on your authentication settings the password may just be sitting out as an encoded byte[] and even the settings that digest it still possibly (I haven't looked too extensively, and I'm not trying to knock PostgreSQL here) leave that digest open to being dug up.

Even if no one ever made a copy of the password String and the digest was completely untouchable, you still have to worry about the fact that there are dangling references to the it (through the Properties object) all over your driver's stack, and things might break in unexpected ways.

For better or worse, I think we're pretty committed to storing DB passwords as Strings at this point, but I'm really not convinced it's a big issue. I don't think the historical experience has been that it's easier for programmers to securely manage the life-cycle of sensitive objects as opposed to the garbage collector. It'd be nice if Java gave us a way to annotate an object as a target for more aggressive pruning, but also probably not necessary.

Just writing this post, I had to go through ~8 levels of method calls and object creation and so I wonder if the password string is really short-lived enough that being able to manually wipe it would significantly decrease attack surface area. I think the convenience as ergonomics of Java's DB handling lets us forget how much is going on behind the scenes.