I learned about using char[] to store password back in Usenet days in comp.lang.java.*.
Searching StackOverflow you can also easily find highly upvoted questsions like this: Why is char[] preferred over String for passwords? which agrees with what I learned a long, long time ago.
I still write my APIs to use char[] for password. But is that just hollow ideals now?
For example, look at Atlassian Jira's Java API: LoginManager.authenticate which takes your password as a String.
Or Thales' Luna Java API: login() method in LunaSlotManager Of all people, a HSM vendor using String for HSM slot password.
I think I've also read somewhere that the internals of URLConnection (and many other classes) uses String internally to handle the data. So if you ever send a password (although the password is encrypted by TLS over the wire), it will be in a String in your server's memory.
Is accessing server memory an attack factor so difficult to achieve, that it is okay to store passwords as String now? Or that your password will end up in a String anyway due to classes written by others, is that why Thales' doing it.
CodePudding user response:
First, let’s recall the reason for the recommendation to use char[]
instead of String
: String
s are immutable, so once the string is created, there is limited control over the contents of the string until (potentially well after) the memory is garbage collected. An attacker that can dump the process memory can thus potentially read the password data. Meanwhile the contents of the char[]
object can be overridden after it has been created. Assuming the GC hasn’t moved the object to another physical memory location in the interim, this means that the password contents can be destroyed (somewhat) deterministically after it has been used. An attacker reading the process memory after that point won’t be able to get the password.
So using char[]
instead of String
prevents a very specific attack scenario: the attacker has full access to the process memory, but only at specific points in time rather than continuously. And even under this scenario, using char[]
does not prevent the attack, it just reduces its chance of success (if the attacker happens to read the process memory between the creation and the erasure of the password, they can read it).
I am not aware of any evidence that shows (a) how frequent this scenario is, nor (b) how much using char[]
changes the probability of success under that scenario. As far as I know, this is pure guesswork.
In fact, on most systems, this scenario likely does not exist at all: an attacker who can get access to another process’ memory can also gain full tracing access. For instance, on both Linux and Windows any process that can read another process’ memory can also inject arbitrary logic into that process (e.g. via LD_PRELOAD
and similar mechanisms1). So I would say that using char[]
at best has a limited benefit, and potentially none at all.
… Actually I can think of one specific counter-example: an application that loads an untrusted plugin library. As soon as that library is loaded via conventional means (i.e. in the same memory space), it has access to the parent application. In this scenario, it might make sense to use char[]
instead of String
if the password is handled before the plugin is loaded. But a better solution would be not to load untrusted plugins into the same memory space. A common alternative is to launch it in a separate process and communicate via IPC.
1 Although LD_PRELOAD
specifically requires the attacker to not only have access to another process but either to launch that process, or to have access to its parent process.
CodePudding user response:
It's not an idea of the moment of transfer over the network. There indeed you're indeed better off using a String as it's just more convient to use to send over the network, of course making sure it's properly encrypted.
For using passwords in applications it's different due to stack-dumps and reverse engineering, and the problem of the String being immutable: In case the password has been entered, even if the reference to the variable is changed to another string, there is no certainty about when the garbage collector will actually remove the String from the heap. So a hacker being able to see the dump will also be able to see the password. Using an array of char prevents this as you can change the data in the array directly without relying on the garbage collector.
Now you might say: well then when sending it over the network as a String it'll still be visible no? Well yes, but that's why encrypting it before sending it is important. Never send plain text passwords over the network when possible.