For security, is it safe to pass new String(char[]) as an argument for passwords to a method that only accepts string as parameter?

Rigo Sarmiento :

I've read that for passwords, it's more ideal to use char[] since Strings are immutable. Problem is, I need to pass a password argument to a third party dependency that invokes an http call. It only accepts strings. The call involves sending in a password in the message, so I use the method:

new Request.Builder()
    .url("notmyapi.com/login")
    .method("POST", new FormBody.Builder()
        .add("name", username)
        .add("password", password)
        .build())
    .build()

I know it's probably bad that the web api is just accepting a password as it is instead of accepting a base64 version or whatever, but it's not mine, and I just simply have to do my job.

Question:

Since I'm now passing around the password as char[], but the .add(key, value) method above accepts only a string, is it safe to do .add("password", new String(password)) ? Will this not create a new String instance in the memory which I'm supposedly trying to avoid for security concerns?

Stephen C :

I've read that for passwords, it's more ideal to use char[] since Strings are immutable.

That's not the (whole) reason. The actual reasoning is:

  1. You are using passwords for security.

  2. A bad guy may be able to get a memory dump of a running JVM ... or extract a partial dump from the disk blocks that hold (or held) the JVM's memory pages. That dump may contain passwords in clear text.

  3. To mitigate this, one can (should) overwrite the memory containing the passwords when they are no longer required.

  4. It is hard to overwrite a String since it is immutable.

But if you examine each of those points, there are assumptions that can be questioned.

  1. Passwords are not a good way of implementing security. For high grade security you should be using public/private key or secret key authentication. So either you are talking about passwords that are "less important" to your system ... or you have a bigger problem than the one you are trying to address here.

  2. If the bad guy can read JVM memory or the page file, they are pretty deep into your infrastructure. You are already fatally compromised. Furthermore, if they are in this deep, they can most likely find other ways to steal the passwords; e.g. stealing your SSL Cert private key and snooping / decoding the encrypted network traffic.

  3. This is only a mitigation:

    • The passwords will be in the clear in the char[] for a period.
    • Before the passwords arrive at your code, they will most likely have been converted to String objects by the servlet stack (or whatever framework you use).
    • Besides, this mitigation is only effective if you do overwrite the char[] in your code.
  4. In fact, if you are really worried about this, it is possible to use reflection to erase a String; i.e. to mutate a String object. In general, this is a dangerous thing to do. For passwords / password checking, this might be acceptable.

In short, I would argue that using char[] instead of String is too expensive to implement in Java .... unless you are prepared to completely re-engineer your web framework. Furthermore, the benefit of doing this debatable, given the other ways that someone with deep access could steal the passwords.


Now to your specific question:

Is it safe to do .add("password", new String(password))

If you consider it to be risky to use a String for a password, then that code doesn't help. In fact, assuming that password is a String you now have two String objects in memory that contain the password text.

  • If the API you are using requires you to provide the password as a String you have a problem.

  • If the source of the password (i.e. how you get it from the user interface, servlet framework, whatever) is a String, you have a problem.

  • Both cases it will be necessary to rework aspects of the code that you are interacting with to solve the problem. This may be difficult.

And:

I know it's probably bad that the web api is just accepting a password as it is instead of accepting a base64 version or whatever.

Base64 won't slow the bad guy down for more than a minute or so. Ditto for any reversible encoding. But I hope that you are insisting that the password only be sent over SSL / TLS secured connections.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=92847&siteId=1