By Ahamed


2012-01-16 14:20:42 8 Comments

In Swing, the password field has a getPassword() (returns char[]) method instead of the usual getText() (returns String) method. Similarly, I have come across a suggestion not to use String to handle passwords.

Why does String pose a threat to security when it comes to passwords? It feels inconvenient to use char[].

16 comments

@Neeraj 2018-12-03 06:31:46

It is debatable as to whether you should use String or use Char[] for this purpose because both have their advantages and disadvantages. It depends on what the user needs.

Since Strings in Java are immutable, whenever some tries to manipulate your string it creates a new Object and the existing String remains unaffected. This could be seen as an advantage for storing a password as a String, but the object remains in memory even after use. So if anyone somehow got the memory location of the object, that person can easily trace your password stored at that location.

Char[] is mutable, but it has the advantage that after its usage the programmer can explicitly clean the array or override values. So when it's done being used it is cleaned and no one could ever know about the information you had stored.

Based on the above circumstances, one can get an idea whether to go with String or to go with Char[] for their requirements.

@ACV 2018-04-25 22:39:55

String is immutable and it goes to the string pool. Once written, it cannot be overwritten.

char[] is an array which you should overwrite once you used the password and this is how it should be done:

char[] passw = request.getPassword().toCharArray()
if (comparePasswords(dbPassword, passw) {
 allowUser = true;
 cleanPassword(passw);
 cleanPassword(dbPassword);
 passw=null;
}

private static void cleanPassword (char[] pass) {
 for (char ch: pass) {
  ch = '0';
 }
}

One scenario where the attacker could use it is a crashdump - when the JVM crashes and generates a memory dump - you will be able to see the password.

That is not necessarily a malicious external attacker. This could be a support user that has access to the server for monitoring purposes. He could peek into a crashdump and find the passwords.

@Yugerten 2018-12-02 22:56:37

ch = null; you can't do this

@ACV 2018-12-02 23:13:04

@Yugerten good point. It's just pseudocode, but yeah

@Human Being 2014-05-08 10:17:46

These are all the reasons, one should choose a char[] array instead of String for a password.

1. Since Strings are immutable in Java, if you store the password as plain text it will be available in memory until the Garbage collector clears it, and since String is used in the String pool for reusability there is a pretty high chance that it will remain in memory for a long duration, which poses a security threat.

Since anyone who has access to the memory dump can find the password in clear text, that's another reason you should always use an encrypted password rather than plain text. Since Strings are immutable there is no way the contents of Strings can be changed because any change will produce a new String, while if you use a char[] you can still set all the elements as blank or zero. So storing a password in a character array clearly mitigates the security risk of stealing a password.

2. Java itself recommends using the getPassword() method of JPasswordField which returns a char[], instead of the deprecated getText() method which returns passwords in clear text stating security reasons. It's good to follow advice from the Java team and adhere to standards rather than going against them.

3. With String there is always a risk of printing plain text in a log file or console but if you use an Array you won't print contents of an array, but instead its memory location gets printed. Though not a real reason, it still makes sense.

String strPassword="Unknown";
char[] charPassword= new char[]{'U','n','k','w','o','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);

String password: Unknown
Character password: [[email protected]

Referenced from this blog. I hope this helps.

@Lucky 2016-11-03 07:57:15

This is redundant. This answer is a exact version of the answer written by @SrujanKumarGulla stackoverflow.com/a/14060804/1793718. Please don't copy paste or duplicate the same answer twice.

@Vaibhav_Sharma 2017-07-28 11:13:36

What is the difference between 1.) System.out.println("Character password: " + charPassword); and 2.) System.out.println(charPassword); Because it is giving the same "unknown" as output.

@skomisa 2019-09-18 03:53:32

@Lucky Unfortunately the older answer you linked to was plagiarized from the same blog as this answer, and has now been deleted. See meta.stackoverflow.com/questions/389144/… . This answer has simply cut and pasted from that same blog and added nothing, so it should have simply been a comment linking to the original source.

@Jon Skeet 2012-01-16 14:26:16

Strings are immutable. That means once you've created the String, if another process can dump memory, there's no way (aside from reflection) you can get rid of the data before garbage collection kicks in.

With an array, you can explicitly wipe the data after you're done with it. You can overwrite the array with anything you like, and the password won't be present anywhere in the system, even before garbage collection.

So yes, this is a security concern - but even using char[] only reduces the window of opportunity for an attacker, and it's only for this specific type of attack.

As noted in the comments, it's possible that arrays being moved by the garbage collector will leave stray copies of the data in memory. I believe this is implementation-specific - the garbage collector may clear all memory as it goes, to avoid this sort of thing. Even if it does, there's still the time during which the char[] contains the actual characters as an attack window.

@Mark Peters 2012-01-16 14:30:09

My understanding is that with the amount of memory reorganizing that can be done with the runtime, copies of even a char[] might be left in memory and never be cleared until that memory is reused. I don't know a source that validates that though. Either way I doubt the String would get cleared at GC time but rather at the time an Object is reallocated over that memory.

@Mnementh 2012-01-16 14:32:25

@Mark Peters: If the GC kicks in, before you empty the char-array, you have another copy. But this copy is at least in a heavy used area of the memory, so the chances are high it gets overwritten fast.

@Jon Skeet 2012-01-16 20:42:39

@Xeon06: In .NET there's SecureString which is better yet - but relatively painful to use.

@supercat 2014-11-29 00:39:06

If a GC causes a char[] to get relocated, the old one might exist for a little while, but would generally be in a place that would 'naturally' get overwritten before the next GC. A problem with String is references to things can sometimes stick around a lot longer than intended (e.g. clearing some implementations of List<T> might reset the count without erasing the backing store). Such things might cause a reference to a string to stick around a long time after all "useful" references have been abandoned.

@Andy Res 2015-01-05 16:24:49

If the immutability is the problem, can we use a StringBuilder or StringBuffer instead?

@Jon Skeet 2015-01-05 21:32:34

@Andy: One issue there is that the values can get copied transparently if you're not careful - so it's still hard to really wipe things out. But I should emphasise that I'm not a security expert.

@Alexandre Pereira Nunes 2015-05-23 16:22:06

The answer covered it all, but just to complement: Java Strings are subject to being stored in a pool (for the specified case, see the String's intern() method, but there could also be implementation dependent pools). A pool is normally a fixed-size cache that only evicts entries when it's fulll, probably using some LRU scheme. All this means that Strings can eventually persist for quite a long time, without being affected by garbage collectors.

@corsiKa 2015-06-12 19:40:56

Are we glossing over the fact that a malicious entity that can read this data already has read memory access to your system? It seems that would be of so much a greater concern that doing this char[] instead of String just seems like pissing in the ocean.

@Jon Skeet 2015-06-12 19:42:19

@corsika: As I mentioned in the answer, it's reducing one specific attack vector, that's all. It makes things harder for an attacker.

@Mohit Kanwar 2015-07-01 05:37:49

@JonSkeet How can passwords(or any string for that matter) stored in stringpool retrieved? I tried lots of forums but was not able to find a way.

@Jon Skeet 2015-07-01 05:56:53

@CodeFighter: First obvious way: dump the entire process's memory, then look for anything "string-like". (Once you've worked out what constitutes one string, the rest is easy as there'll be a reference to the string type within each string object.)

@Rolf 2015-07-14 08:56:58

More info on storing Passwords in Strings in Java is on the Security Stackexchange: security.stackexchange.com/questions/6753/…

@Yeti 2015-09-01 11:26:52

If a process has access to memory of your application, then that is already a security breach, right?

@Jon Skeet 2015-09-01 11:47:16

@Yeti: Yes, but it's not like it's black and white. If they can only get a snapshot of the memory then you want to reduce how much damage that snapshot can do, or reduce the window during which a really serious snapshot can be taken.

@Milixyron 2016-05-31 20:53:17

What about CharSequence? is it almost the same as String? I just saw, that CharSequence has less methods to work with.

@Jon Skeet 2016-06-01 09:46:28

@Milixyron: Well CharSequence is just an interface, which String implements. It doesn't provide any way of clearing it, leading to the same problems.

@Ted Hopp 2016-09-05 19:11:24

A common attack method is to run a process that allocates lots of memory and then scans it for left-over, useful data like passwords. The process doesn't need any magical access to another process's memory space; it just relies on other processes dying without first clearing out sensitive data and the OS also not clearing memory (or page buffers) before making it available to a new process. Clearing out passwords stored in char[] locations cuts off that line of attack, something not possible when using String.

@Ungeheuer 2017-02-08 05:12:33

How would someone snatch a String out of garbage collection?

@Jon Skeet 2017-02-08 06:41:54

@Adrian: With tools to dump a process's memory. They exist for pretty much every platform. Yes, you need to have a fair amount of access to the machine to start with, but it still increases the attacks you can do.

@Holger 2017-03-09 09:59:03

@Ted Hopp: so the only obstacle is to find an OS that does not clearing the memory before making it available to a new process…

@Ted Hopp 2017-03-09 16:53:27

@Holger - You mean like Windows or Linux? And let's not forget the paging areas on hard drives. Any OS that wiped all of that for every process would slow to a crawl unless it had special hardware support. It's up to the process obtaining memory to clear it if that's what it needs. (The difference between malloc and calloc, for instance, is whether you get an uninitialized memory block or one that's been cleared. A data sniffing program probably wouldn't be using calloc.)

@Holger 2017-03-09 17:22:22

@Ted Hopp: I can’t speak for Linux, but Windows does clear memory pages. It’s not clear why this should be slow at all, that happens once for each allocated page and it doesn’t even need to happen on the allocation, but the first actual use, though there’s also a background clearing of unused pages in advance when CPU cycles are free. The reason is exactly security. That doesn’t affect the difference between malloc and calloc as these are not operating system, C library functions. So malloc might return non-zero memory which the same program has freed earlier…

@Ted Hopp 2017-03-09 18:21:47

@Holger - Interesting. It seems that Windows has tightened up security quite a bit. The CVE database contains a large list of memory exploits for Windows XP and Windows 7. Then there's this interesting blog post on How to Read and Write Other Process Memory on Windows and Linux.

@Holger 2017-03-09 18:29:48

@Ted Hopp: well, this blog uses explicit access to process memory of other processes, which should be (and surely is) subject to access checking and won’t work, if you try to read the memory of a privileged process. That’s different to attempts to find accidentally left over artifacts in newly allocated memory. The security bugs are, as far as I can see, also not related to artifacts in allocations, however, there are enough other bugs left in Windows…

@JIE WANG 2017-06-26 17:06:01

Hi, @JonSkeet when you talk about there's no way (aside from reflection) you can get rid of the data before garbage collection kicks in., you said the reason is Strings are immutable, is it related to run-time constant pool? or do you have a doc for a deep explanation for this?

@Jon Skeet 2017-06-26 18:09:52

@JIEWANG: Not particularly - we're not talking about constants here... we're talking about strings that have been created probably from user input.

@MasterJoe2 2018-07-25 17:55:50

@JonSkeet - In this question stackoverflow.com/questions/22397861/…, most answers say that String immutability is great for security, which is opposite of your answer here. Their "reasoning" - Strings are often used to store connections, passwords etc. and immutability prevents them from being changed. They don't mention how a Mutable string value getting changed could be a security problem. There is no mention of techniques that can be used to change mutable Strings. Could you please clarify ? Thanks.

@Jon Skeet 2018-07-25 21:24:09

@testerjoe2: Different concerns, I'd say. String immutability is great for making sure that within a constrained sandbox (reflection banned etc) you can pass strings to arbitrary code without worrying about them being mutated. char[] is good for wiping the content of memory to prevent later unguarded code from "spying" on it.

@Dawesi 2018-08-05 19:40:45

How would you then handle a password then that is submitted as a string from the browser in the request scope where the hacker would be looking (aka it's in memory as a string anyway)? does this not defeat the entire point of this?

@Jon Skeet 2018-08-06 05:55:56

@Dawesi: Yes, it's not always possible to treat it as a char[].

@user1485864 2018-09-06 12:10:17

Already plenty of comments, but there is also the security requirement that sensitive data should not be logged. For example, in case your server node crashes, you typically get a HeapDump. You may be able to find password strings in that HeapDump, see Eclipse MAT. But if you use a char[] and you overwrite all elements after you have read it, you effectively remove the password from the memory and hence from the HeapDump. And HeapDumps are typically stored in companys' NAS, so ... This is something that needs to be done for other sensitive data too, like credit card numbers, etc.

@code_dredd 2018-11-13 23:53:58

@JonSkeet And for those who may be late to the party, or just leisure reading like me, note that SecureString class should not be used anymore.

@Pritam Banerjee 2016-12-09 19:02:54

The short and straightforward answer would be because char[] is mutable while String objects are not.

Strings in Java are immutable objects. That is why they can't be modified once created, and therefore the only way for their contents to be removed from memory is to have them garbage collected. It will be only then when the memory freed by the object can be overwritten, and the data will be gone.

Now garbage collection in Java doesn't happen at any guaranteed interval. The String can thus persist in memory for a long time, and if a process crashes during this time, the contents of the string may end up in a memory dump or some log.

With a character array, you can read the password, finish working with it as soon as you can, and then immediately change the contents.

@pmcilreavy 2017-01-31 10:22:04

This is just a pointless rehash of Skeet's answer.

@Pritam Banerjee 2017-09-11 06:02:41

@fallenidol Not at all. Read carefully and you will find the differences.

@Saathvik 2017-07-28 06:33:06

String in java is immutable. So whenever a string is created, it will remain in the memory until it is garbage collected. So anyone who has access to the memory can read the value of the string.
If the value of the string is modified then it will end up creating a new string. So both the original value and the modified value stay in the memory until it is garbage collected.

With the character array, the contents of the array can be modified or erased once the purpose of the password is served. The original contents of the array will not be found in memory after it is modified and even before the garbage collection kicks in.

Because of the security concern it is better to store password as a character array.

@Oleg Mikheev 2015-01-24 07:43:40

There is nothing that char array gives you vs String unless you clean it up manually after use, and I haven't seen anyone actually doing that. So to me the preference of char[] vs String is a little exaggerated.

Take a look at the widely used Spring Security library here and ask yourself - are Spring Security guys incompetent or char[] passwords just don't make much sense. When some nasty hacker grabs memory dumps of your RAM be sure she'll get all the passwords even if you use sophisticated ways to hide them.

However, Java changes all the time, and some scary features like String Deduplication feature of Java 8 might intern String objects without your knowledge. But that's different conversation.

@Holger 2017-03-09 17:45:27

Why is String-deduplication scary? It only applies when there are at least two strings having the same contents, so what danger would arise from letting these two already identical strings share the same array? Or lets ask the other way round: if there is no string-deduplication, what advantage arises from the fact that both strings have a distinct array (of the same contents)? In either case, there will be an array of that contents being alive at least as long as the longest living String of that contents is alive…

@Oleg Mikheev 2017-03-09 18:28:56

@Holger anything that's out of your control is a potential risk... for instance if two users have the same password this wonderful feature will store both of them in single char[] making it evident that they are the same, not sure if that's a huge risk but still

@Holger 2017-03-09 18:35:04

If you have access to the heap memory and both string instances, it doesn’t matter whether the strings point to the same array or to two arrays of the same contents, each is easy to find out. Especially, as it is irrelevant anyway. If you are at this point, you grab both passwords, whether identical or not. The actual error lies in using plaintext passwords instead of salted hashes.

@Oleg Mikheev 2017-03-10 21:40:43

@Holger to verify password it has to be in clear text in memory for some time, 10ms, even if it's just to create a salted hash out of it. Then, if it happens that there are two identical passwords kept in memory even for 10 ms, deduplication may come into play. If it really interns strings they are kept in memory for much longer time. System that doesn't restart for months will collect lots of these. Just theorizing.

@Holger 2017-03-13 11:30:41

It seems, you have a fundamental misunderstanding about String Deduplication. It doesn’t “intern strings”, all it does, is letting strings with the same contents point to the same array, which actually reduces the number of array instances containing the plaintext password, as all but one array instance can be reclaimed and overwritten by other objects immediately. These strings are still collected like any other string. Maybe it helps, if you understand that the de-duplication is actually done by the garbage collector, for strings that have survived multiple GC cycles only.

@nobar 2019-09-17 16:58:35

"are Spring Security guys incompetent": It's an important question in this context. I previously wondered this myself, when looking into the differences between BCrypt and BCryptPasswordEncoder. Even in the simultaneous initial commit they took an inconsistent approach: taking String for Bcrypt and taking CharSequence for BCryptPasswordEncoder (which calls Bcrypt).

@Graph Theory 2015-04-08 00:04:59

Edit: Coming back to this answer after a year of security research, I realize it makes the rather unfortunate implication that you would ever actually compare plaintext passwords. Please don't. Use a secure one-way hash with a salt and a reasonable number of iterations. Consider using a library: this stuff is hard to get right!

Original answer: What about the fact that String.equals() uses short-circuit evaluation, and is therefore vulnerable to a timing attack? It may be unlikely, but you could theoretically time the password comparison in order to determine the correct sequence of characters.

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        // Quits here if Strings are different lengths.
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            // Quits here at first different character.
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

Some more resources on timing attacks:

@Mohit Kanwar 2015-07-01 05:41:56

But that could be there in char[] comparison as well, somewhere we would be doing the same in password validation too. so how is char[] better than string?

@Graph Theory 2015-07-02 21:03:09

You're absolutely correct, the mistake can be made either way. Knowing about the problem is the most important thing here, considering there's no explicit password-comparison method in Java for either String-based or char[]-based passwords. I'd say the temptation to use compare() for Strings is a good reason to go with char[]. That way you at least have control over how the comparison is done (without extending String, which is a pain imo).

@Holger 2017-03-09 10:22:44

Besides comparing plaintext passwords isn’t the right thing anyway, the temptation to use Arrays.equals for char[] is as high as for String.equals. If anyone cared, there was a dedicated key class encapsulating the actual password and taking care of the issues—oh wait, the real security packages have dedicated key classes, this Q&A is only about a habit outside of them, say, e.g. JPasswordField, to use char[] instead of String (where the actual algorithms use byte[] anyway).

@Holger 2017-03-09 10:24:40

Security relevant software should do something like sleep(secureRandom.nextInt()) before rejecting a login attempt anyway, that’s not only removing the possibility of timing attacks, it also makes counteracts brute force attempts.

@Geek 2015-07-28 10:46:40

Strings are immutable and cannot be altered once they have been created. Creating a password as a string will leave stray references to the password on the heap or on the String pool. Now if someone takes a heap dump of the Java process and carefully scans through he might be able to guess the passwords. Of course these non used strings will be garbage collected but that depends on when the GC kicks in.

On the other side char[] are mutable as soon as the authentication is done you can overwrite them with any character like all M's or backslashes. Now even if someone takes a heap dump he might not be able to get the passwords which are not currently in use. This gives you more control in the sense like clearing the Object content yourself vs waiting for the GC to do it.

@avgvstvs 2016-02-05 15:15:30

They'll only be GC'd if the JVM in question is > 1.6. Prior to 1.7, all strings were stored in permgen.

@Holger 2017-03-09 10:28:15

@avgvstvs: “all strings were stored in permgen” is just dead wrong. Only interned strings were stored there and if they weren’t originating from string literals referenced by code, they were still garbage collected. Just think about it. If strings were generally never GCed in JVMs prior to 1.7, how could any Java application survive more than a few minutes?

@avgvstvs 2017-03-09 16:36:36

@Holger This is false. Interned strings AND the String pool (pool of previously used strings) were BOTH stored in Permgen prior to 1.7. Also, See section 5.1: docs.oracle.com/javase/specs/jvms/se6/html/… The JVM always checked Strings to see if they were the same reference value, and would call String.intern() FOR YOU. The result was that every time the JVM detected identical Strings in the constant_pool or heap it would move them into permgen. And I worked on several applications with "creeping permgen" until 1.7. It was a real problem.

@avgvstvs 2017-03-09 16:39:51

So to recap: Until 1.7, Strings started in the heap, when they were used they were put into the constant_pool which was located IN permgen, and then if a string was used more than once, it would be interned.

@Holger 2017-03-09 17:34:37

@avgvstvs: There is no “pool of previously used strings”. You are throwing entirely different things together. There is one runtime string pool containing string literals and explicitly interned string, but no other. And each class has its constant pool containing compile-time constants. These strings are automatically added to the runtime pool, but only these, not every string.

@josefx 2012-01-16 14:32:25

Some people believe that you have to overwrite the memory used to store the password once you no longer need it. This reduces the time window an attacker has to read the password from your system and completely ignores the fact that the attacker already needs enough access to hijack the JVM memory to do this. An attacker with that much access can catch your key events making this completely useless (AFAIK, so please correct me if I am wrong).

Update

Thanks to the comments I have to update my answer. Apparently there are two cases where this can add a (very) minor security improvement as it reduces the time a password could land on the hard drive. Still I think it's overkill for most use cases.

  • Your target system may be badly configured or you have to assume it is and you have to be paranoid about core dumps (can be valid if the systems are not managed by an administrator).
  • Your software has to be overly paranoid to prevent data leaks with the attacker gaining access to the hardware - using things like TrueCrypt (discontinued), VeraCrypt, or CipherShed.

If possible, disabling core dumps and the swap file would take care of both problems. However, they would require administrator rights and may reduce functionality (less memory to use) and pulling RAM from a running system would still be a valid concern.

@Joachim Sauer 2012-01-16 16:23:17

I'd replace "completely useless" with "just a minor security improvement". For example you could get access to a memory dump if you happen to have read access to a tmp directory, a badly configured machine and a crash in your application. In that case you wouldn't be able to install a keylogger, but you could analyze the core dump.

@Dan Neely 2012-01-16 16:26:12

Wiping unencrypted data from memory as soon as you're done with it is considered a best practice not because it's foolproof (it's not); but because it reduces your threat exposure level. Real time attacks aren't prevented by doing this; but because it serves a a damage mitigation tool by significantly reduces the amount of data that is exposed in a retroactive attack on a memory snapshot (eg a copy of your apps memory that was written to a swap file, or that was read out of memory yanked from a running server and moved to a different one before its state failed).

@kingdango 2012-01-17 18:18:47

I tend to agree with the attitude of this response. I'd venture to propose most security breaches of consequence occur at a much higher level of abstraction than the bits in memory. Sure, there are probably scenarios in hyper-secure defense systems where this may be of considerable concern but seriously thinking at this level is overkill for 99% of the applications where .NET or Java are being leveraged (as it related to garbage collection).

@Rolf Rander 2012-01-20 17:19:12

maybe localhost isn't what you want to protect. Maybe you have created a program running on an unsecure client and you need the password for accessing a database. If you don't trust the client and are trying to protect the database, wiping passwords from memory is good advice.

@josefx 2012-01-20 19:08:47

@RolfRander that is even worse, you should not enter passwords on an untrusted client - use a one time key (not sure this is the right term, a password that only works once and gets locked out after that use).

@Rolf Rander 2012-01-20 19:31:47

most websites use passwords for login. Your credit card number and security-digits is also a kind of password.

@josefx 2012-01-20 20:58:09

@RolfRander there is nothing about websites that requires an untrusted client, if the user chooses to use a compromised system then there is nothing that you can do to protect him from the consequences.

@Rolf Rander 2012-01-20 22:02:51

as I said, the point might be protecting the server, not the client. My point with the website-example is that there are lots of services using passwords (for different reasons, although other mechanisms obviously would be more secure. Bottom line being that a scenario where you want to protect the server, won't trust the client and are using passwords, storing passwords in a char[] is a wise choice and this isn't really a far-fetched scenario.

@josefx 2012-01-21 10:06:35

@RolfRander somehow I get the feeling that you use a single login for all your clients and don't have any security/validation serverside. Its your duty to make sure that a user can't compromise the database (access restrictions and validation serverside) and the users duty to make sure that his account can't be compromised (his password).

@Rolf Rander 2012-01-22 11:49:38

Absolutely. But for the user to make sure his password isn't compromised, the software handling the password has to take care to reduce the chance that malware (on the client) can pick up passwords from the client application memory. To achieve that, I believe storing the password in a char[] and overwriting this afterwards is good advice.

@Tinman 2012-10-10 21:28:23

I'd say that of someone understands the thinking behind the char vs sting then they are more likely to be thinking of security when configuring the servers. Not thinking is what usually introduces security holes.

@Peter vdL 2014-07-24 05:15:05

After the Heartbleed penetration of server memory, revealing passwords, I would replace the string "just a minor security improvement" with "absolutely essential to not use String for passwords, but use a char [] instead."

@josefx 2014-07-26 14:47:53

@PetervdL heartbleed happened because someone got the great idea that reusing memory was cheaper than allocating new (cleared) memory, you cannot reuse a String in Java, just hope that nobody ever gets the idea to put your char[] into a reuse list for better performance.

@Peter vdL 2014-07-27 18:45:48

You're missing the point completely, Josefx. The point is that heartbleed allowed remote reading of process memory, which everyone had hitherto thought very unlikely. When combined with the use of Java strings, passwords are easily revealed. Char [] allows the developer to blank out passwords, String does not even give that opportunity. Char [] + heartbleed may be harmful if coder screws up. String + heartbleed == definitely always harmful.

@josefx 2014-07-30 17:39:33

@PetervdL heartbleed only allowed reading of a specific reused collection of buffers (used for both security critical data and network I/O without clearing in between - for performance reasons), you cannot combine this with a Java String since they are by design not reuseable. Nor can you read into random memory using Java to get at the contents of a String. The language and design problems that lead to heartbleed are just not possible with Java Strings.

@josefx 2014-07-31 19:39:28

@PetervdL then please do not refer the "heartbleed bug in combination with Java Strings" and I am sure most I mentioned in relation to heartbleed was correct, the libreSSL developers got quite detailed on why OpenSSL was a security nightmare. There "may" be a way to use a bug in the JIT to bypass Javas build in range checks or the automatic zeroing of object memory and it "might" be possible for someone to trigger this from a remote location without crashing the JVM, however that has nothing in common with heartbleed, nor would any bug on the JVM be so simple or optimized for exploits.

@DavidS 2015-07-08 05:15:50

@PetervdL It's not just not "specific" to the Heartbleed bug; it's totally inapplicable. I suggest you don't reference Heartbleed as justification for security measures until you have a better grasp of its nature. Thanks to josefx for shedding light on this often misunderstood issue.

@ACV 2018-04-25 22:33:09

There is yet another case - when the JVM crashes and produces a memory dump.

@Dawesi 2018-08-05 19:59:21

Why would you store the password in in memory? external system? web or api request submits a string (ironically), so it's in memory anyway at that point. I'd never store the login password in another variable (other than the readonly one it's sent to the server with) unencrypted for any reason? Should web requests convert letters to their char number equiv to submit so the request variable is a number? As there is no char datatype from the browser?

@Stefan L 2018-12-17 16:18:08

And for completeness let's not forget the more recent meltdown and spectre attacks: meltdownattack.com which could be exploited via a web browser or shared hosting environment.

@Peter Lawrey 2015-07-08 09:26:55

As Jon Skeet states, there is no way except by using reflection.

However, if reflection is an option for you, you can do this.

public static void main(String[] args) {
    System.out.println("please enter a password");
    // don't actually do this, this is an example only.
    Scanner in = new Scanner(System.in);
    String password = in.nextLine();
    usePassword(password);

    clearString(password);

    System.out.println("password: '" + password + "'");
}

private static void usePassword(String password) {

}

private static void clearString(String password) {
    try {
        Field value = String.class.getDeclaredField("value");
        value.setAccessible(true);
        char[] chars = (char[]) value.get(password);
        Arrays.fill(chars, '*');
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

when run

please enter a password
hello world
password: '***********'

Note: if the String's char[] has been copied as a part of a GC cycle, there is a chance the previous copy is somewhere in memory.

This old copy wouldn't appear in a heap dump, but if you have direct access to the raw memory of the process you could see it. In general you should avoid anyone having such access.

@chux - Reinstate Monica 2015-08-27 19:21:55

Better to do also something to prevent printing the password's length which we get from '***********'.

@Peter Lawrey 2015-08-27 20:16:36

@chux you can use a zero width character, though this might be more confusing than useful. Its not possible to change the length of a char array without using Unsafe. ;)

@jamp 2016-02-08 14:48:49

Because of Java 8's String Deduplication, I think doing something like that can be pretty destructive... you may end up clearing other strings in your program that by chance had the same value of the password String. Unlikely, but possible...

@Peter Lawrey 2016-02-08 15:33:27

@jamp Java 9 is expected to have this feature as well as compact string (i.e. using a byte[]]). I don't believe this happens in Java 8.

@jamp 2016-02-08 16:20:53

@PeterLawrey It must be enabled with a JVM argument, but it is there. Can read about it here: blog.codecentric.de/en/2014/08/…

@alephx 2012-01-16 14:27:33

Character arrays (char[]) can be cleared after use by setting each character to zero and Strings not. If someone can somehow see the memory image, they can see a password in plain text if Strings are used, but if char[] is used, after purging data with 0's, the password is secure.

@avgvstvs 2016-02-05 15:19:41

Not secure by default. If we're talking a web application, most web containers will pass the password into the HttpServletRequest object in plaintext. If the JVM version is 1.6 or lower, it'll be in permgen space. If it's in 1.7, it'll still be readable until it gets collected. (Whenever that is.)

@Holger 2017-03-09 10:04:48

@avgvstvs: strings are not automatically moved to the permgen space, that only applies to intern'ed strings. Besides that, the permgen space is also subject to garbage collection, just at a lower rate. The real issue with the permgen space is it’s fixed size, which is exactly the reason why no one should mindlessly call intern() on arbitrary strings. But you are right in that the String instances exist in the first place (until collected) and turning them into char[] arrays afterwards doesn’t change it.

@avgvstvs 2017-03-09 16:43:12

@Holger see docs.oracle.com/javase/specs/jvms/se6/html/… "Otherwise, a new instance of class String is created containing the sequence of Unicode characters given by the CONSTANT_String_info structure; that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked." In 1.6, the JVM would call intern for you when it detected identical sequences.

@Holger 2017-03-09 17:28:00

@avgvstvs: this is relevant to the constant pool entries of a class, describing string literals, only. The constant pool of a class contains, as the name suggests, only constant strings, which obviously must be known at compile time (how could they appear in the class file otherwise). Strings created at runtime, i.e. via Stringbuilder or one of the constructors of String are not affected.

@avgvstvs 2017-03-11 18:43:21

@Holger, you are correct I conflated constant pool and string pool, but it is also false that permgen space only applied to interned strings. Prior to 1.7, both the constant_pool and the string_pool resided in permgen space. That means the only class of Strings that were allocated to the heap were as you said, new String() or StringBuilder.toString() I managed applications with lots of string constants, and we had lots of permgen creep as a result. Until 1.7.

@Holger 2017-03-13 11:20:49

@avgvstvs: well, string constants are, as the JLS mandates, always interned, hence the statement that interned strings ended up in the permgen space, applied to string constants implicitly. The only difference is that string constants were created in the permgen space in the first place, whereas calling intern() on an arbitrary string could cause the allocation of an equivalent string in the permgen space. The latter could get GC’ed, if there was no literal string of the same contents sharing that object…

@roottraveller 2017-10-31 06:56:49

simple words, +1.

@Joshua Taylor 2018-03-15 18:47:34

Neat to note, though, that some information about the string is still leaked (if memory can be inspected): the length of the password. With a C style string, we could just have a buffer of memory and once it's nulled out, we don't know how long the original string was. With the char[] in Java, we do. If an attacker can see memory, and sees that getPassword() returns a char[1], that indicates a much easier brute force target than one that returns a char[16].

@Dawesi 2018-08-05 19:42:20

Isn't password submitted as a string from the browser? aka in memory as a string before you start?

@emboss 2012-01-19 19:39:47

The answer has already been given, but I'd like to share an issue that I discovered lately with Java standard libraries. While they take great care now of replacing password strings with char[] everywhere (which of course is a good thing), other security-critical data seems to be overlooked when it comes to clearing it from memory.

I'm thinking of e.g. the PrivateKey class. Consider a scenario where you would load a private RSA key from a PKCS#12 file, using it to perform some operation. Now in this case, sniffing the password alone wouldn't help you much as long as physical access to the key file is properly restricted. As an attacker, you would be much better off if you obtained the key directly instead of the password. The desired information can be leaked manifold, core dumps, a debugger session or swap files are just some examples.

And as it turns out, there is nothing that lets you clear the private information of a PrivateKey from memory, because there's no API that lets you wipe the bytes that form the corresponding information.

This is a bad situation, as this paper describes how this circumstance could be potentially exploited.

The OpenSSL library for example overwrites critical memory sections before private keys are freed. Since Java is garbage-collected, we would need explicit methods to wipe and invalidate private information for Java keys, which are to be applied immediately after using the key.

@Bruno 2012-01-21 13:31:55

One way around this is to use an implementation of PrivateKey that doesn't actually load its private content in memory: via a PKCS#11 hardware token for example. Perhaps a software implementation of PKCS#11 could take care of cleaning up the memory manually. Perhaps using something like the NSS store (which shares most of its implementation with the PKCS11 store type in Java) is better. The KeychainStore (OSX keystore) loads the full content of the private key into its PrivateKey instances, but it should not need to. (Not sure what the WINDOWS-MY KeyStore does on Windows.)

@emboss 2012-01-21 14:18:47

@Bruno Sure, hardware-based tokens do not suffer from this, but what about situations where you are more or less forced to use a software key? Not every deployment has the budget to afford an HSM. Software key stores will at some point have to load the key into memory, so IMO we should at least be given the option to clear the memory at will again.

@Bruno 2012-01-21 14:29:30

Absolutely, I was just wondering whether some software implementations equivalent to an HSM might behave better in terms of cleaning up the memory. For example, when using client-auth with Safari/OSX, the Safari process never actually sees the private key, the underlying SSL library provided by the OS talks directly to the security daemon which prompts the user for using the key from the keychain. While this is all done in software, a similar separation like this may help if signing is delegated to a different entity (even software based) that would unload or clear the memory better.

@emboss 2012-01-21 14:45:09

@Bruno: Interesting idea, an additional indirection layer that takes care of clearing the memory would indeed solve this transparently. Writing a PKCS#11 wrapper for the software key store could already do the trick?

@Konrad Garus 2012-01-16 19:37:30

While other suggestions here seem valid, there is one other good reason. With plain String you have much higher chances of accidentally printing the password to logs, monitors or some other insecure place. char[] is less vulnerable.

Consider this:

public static void main(String[] args) {
    Object pw = "Password";
    System.out.println("String: " + pw);

    pw = "Password".toCharArray();
    System.out.println("Array: " + pw);
}

Prints:

String: Password
Array: [[email protected]

@bestsss 2012-01-18 01:14:03

@voo, but i doubt you'd log via direct writing to stream and concatenation. logging framework would transform the char[] into good output

@Konrad Garus 2012-01-20 12:39:51

@Thr4wn Default implementation of toString is [email protected]. [C represents char[], the rest is hexadecimal hash code.

@mauhiz 2015-07-09 08:36:07

Interesting idea. I would like to point out that this does not transpose to Scala which has a meaningful toString for arrays.

@rightfold 2015-08-31 17:32:12

I'd write a Password class type for this. It's less obscure, and harder to accidentally pass somewhere.

@GC_ 2016-08-22 11:36:50

@Voo I agree with bestsss. Your logging framework will determine how the char array is printed. I think in most scenarios a char array will get printed.

@GC_ 2016-08-22 13:23:01

Why would someone assume the char array was going to be cast as an Object? I'm not sure I get why every likes this answer. Suppose you did this: System.out.println("Password".toCharArray());

@g.rocket 2017-06-20 00:07:25

Given that Java's hashcode implementation for arrays is not a secure hash, an attacker who found [[email protected] in a logfile could likely bruteforce the password it came from anyways, so this provides a negligible security benefit.

@Octavia Togami 2017-07-12 00:03:29

@g.rocket The hashcode for an array does not depend on the contents of the array, it is effectively random: Online Example

@ACV 2018-04-25 22:31:21

This is not the reason why char[] is recommended instead of String

@Dawesi 2018-08-05 19:46:21

Why is a password stored unencrypted in the first place? It is received in memory from a request (stored in memory as string??) then immediately should be hashed, compared and discarded, or if for another system should be obtained from an external vault already encrypted then decrypted on use using a rotated key? Am I missing something here, trying to get my head around this?

@luis.espinal 2019-01-03 14:54:16

The password might not be stored unencrypted - in fact, what's stored is a securely encrypted and hashed sequence of bytes generated from a password that has been 1) nonced, 2) salted, and 3) lengthened. Let's call that byte sequence C. However, somewhere along the line, a plaintext might be handled to salt/nonce/lengthen then encrypt to compare with C. So the best approach is to always assume that passwordy-looking thingie we are about to hold is plaintext and store it as ephemerally as possible.

@Bruno 2012-01-17 03:20:57

To quote an official document, the Java Cryptography Architecture guide says this about char[] vs. String passwords (about password-based encryption, but this is more generally about passwords of course):

It would seem logical to collect and store the password in an object of type java.lang.String. However, here's the caveat: Objects of type String are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of a String after usage. This feature makes String objects unsuitable for storing security sensitive information such as user passwords. You should always collect and store security sensitive information in a char array instead.

Guideline 2-2 of the Secure Coding Guidelines for the Java Programming Language, Version 4.0 also says something similar (although it is originally in the context of logging):

Guideline 2-2: Do not log highly sensitive information

Some information, such as Social Security numbers (SSNs) and passwords, is highly sensitive. This information should not be kept for longer than necessary nor where it may be seen, even by administrators. For instance, it should not be sent to log files and its presence should not be detectable through searches. Some transient data may be kept in mutable data structures, such as char arrays, and cleared immediately after use. Clearing data structures has reduced effectiveness on typical Java runtime systems as objects are moved in memory transparently to the programmer.

This guideline also has implications for implementation and use of lower-level libraries that do not have semantic knowledge of the data they are dealing with. As an example, a low-level string parsing library may log the text it works on. An application may parse an SSN with the library. This creates a situation where the SSNs are available to administrators with access to the log files.

@bestsss 2012-01-22 20:45:20

this is exactly the flawed/bogus reference I talk about below Jon's answer, it's a well known source w/ a lot of criticism.

@user961954 2012-08-11 11:27:37

@bestass can you please also cite a reference?

@SnakeDoc 2014-06-27 00:50:21

@bestass sorry, but String is pretty well understood and how it behaves in the JVM... there are good reasons to use char[] in place of String when dealing with passwords in a secure manner.

@Dawesi 2018-08-05 19:50:24

once again though the password is passed as a string from the browser to the request as 'string' not char? so no matter what you do it's a string, at which point it should be acted on and discarded, never stored in memory?

@luis.espinal 2019-01-03 19:25:05

@Dawesi - At which point - that's application specific, but the general rule is to do so as soon as you get a hold of something that is supposed to be a password (plaintext or otherwise). You get it from the browser as part of an HTTP request, for instance. You cannot control the delivery, but you can control your own storage, so as soon as you get it, put it in a char[], do what you need to do with it, then set all to '0' and let the gc reclaim it.

@Sean Owen 2012-01-16 14:27:54

I don't think this is a valid suggestion, but, I can at least guess at the reason.

I think the motivation is wanting to make sure that you can erase all trace of the password in memory promptly and with certainty after it is used. With a char[] you could overwrite each element of the array with a blank or something for sure. You can't edit the internal value of a String that way.

But that alone isn't a good answer; why not just make sure a reference to the char[] or String doesn't escape? Then there's no security issue. But the thing is that String objects can be intern()ed in theory and kept alive inside the constant pool. I suppose using char[] forbids this possibility.

@Groo 2012-01-16 17:26:50

I wouldn't say that the problem is that your references will or will not "escape". It's just that strings will remain unmodified in memory for some additional time, while char[] can be modified, and then it's irrelevant whether it's collected or not. And since string interning needs to be done explicitly for non-literals, it's the same like telling that a char[] can be referenced by a static field.

@Dawesi 2018-08-05 19:43:17

isn't password in memory as a string from the form post?

Related Questions

Sponsored Content

42 Answered Questions

[SOLVED] How do I convert a String to an int in Java?

9 Answered Questions

[SOLVED] Why is subtracting these two times (in 1927) giving a strange result?

  • 2011-07-27 08:15:58
  • Freewind
  • 632644 View
  • 6635 Score
  • 9 Answer
  • Tags:   java date timezone

59 Answered Questions

[SOLVED] How to replace all occurrences of a string?

58 Answered Questions

[SOLVED] How do I read / convert an InputStream into a String in Java?

65 Answered Questions

[SOLVED] What is the difference between String and string in C#?

26 Answered Questions

3 Answered Questions

76 Answered Questions

[SOLVED] How do I iterate over the words of a string?

  • 2008-10-25 08:58:21
  • Ashwin Nanjappa
  • 2143163 View
  • 2900 Score
  • 76 Answer
  • Tags:   c++ string split

6 Answered Questions

[SOLVED] Why does Google prepend while(1); to their JSON responses?

26 Answered Questions

Sponsored Content