I am trying to improve the user experience on registration by not requiring the user to retype their password if validation on other fields fail. There are a few ways to implement this, example using session cookie and storing a hash of the password on the server side. I am exploring this alternative of storing user password temporarily on the client side without having the server to keep track of it. Is this method feasible? What are the risks involved?
4 Answers
In principle, values stored in sessionStorage are restricted to the same scheme + hostname + unique port, and if the browser has a clean exit these values should be deleted at the end of the session. However, according to this post it can survive a browser restart if the user chooses to "restore the session" after a crash (which means its values also exist in persistent memory until they are cleared, so keep that in mind). If well implemented, I'd say it's safe enough - especially compared to your alternative of using a cookie (which has many pitfalls that I wouldn't even consider). The W3C Specification also states that Web Storage might indeed be used to store sensitive data (though it's unclear whether or not that practice is endorsed).
As for the risks, it's simply a matter of tradeoffs: you're making your site a little more convenient for your users, while increasing a little the window of opportunity for the password to be captured (either by means of a XSS vulnerability, by the value persisting in persistent storage for longer than you intended to, or by the user leaving the computer unattended before finishing registration). Ideally, passwords should never leave RAM, but that's usually impractical to do, so some compromise is necessary. I'd just advise to clear the password from sessionStorage as soon as the registration succeeds, and to keep an eye for vulnerabilities on sessionStorage implementations that may eventually come to light.
-
Thanks. I am waiting for others to comment. An upvote to get things started. Commented Jun 5, 2013 at 6:57
-
I accepted your answer because it addresses my concern on sessionStorage security most directly. Commented Jun 14, 2013 at 8:55
-
2I don't agree with this statement: "The W3C Specification also states that Web Storage can indeed be used to store sensitive data." The spec appears to be a warning to browser builders to be as careful as possible rather than an endorsement of the practice of storing "potentially sensitive" data in this way. Commented Apr 24, 2015 at 14:35
-
@juanitogan Agreed. I rephrased the statement a bit, to make this point more clear. Commented Apr 24, 2015 at 15:16
I suggest another approach: Instead of submitting the form to the server, use an XMLHttpRequest to create the account. If server side validation fails, the form and all its content is still available. If it was successful, redirect to the target page.
This requires that JavaScript is enabled, but you still can fall back to normal form submission. Access to SessionStorage requires JavaScript as well anyway.
You will be having hard time deciding on which of the two stored values to use as the user's intended password (the one in the local storage, or the one in the input field), if none of them are empty but for some reason differ.
This can potentially provide for a social engineering attack vector, where the attacker prepares a trap by opening the registration form, filling the local/session storage either by using you own code and later removing any traces of it (input error notifications) with a DOM editor, or entering desired password directly in local/session storage (both is supported on some browsers and extremely easy to do), then later asking the victim to register with your website and, well, use it. Since your code can be easily inspected/tested to see how you handle such cases, the attacker might do this slightly differently than what I described (even script injections directly in local/session storage aren't out of the question, if you later process that value locally on form POST), but to same effect.
The victim won't suspect anything until she logs out and tries to log back in. Depending on how persistent the user session is, this process of logging out and logging back in might not be necessary, and the victim wouldn't have noticed her password wasn't the one she entered in the password field, but instead the attacker's password of choice was used to create her new account.
Needles to say, the attacker just gained access to the victim's newly created account and all the data the victim entered, even if the victim was cautious and made sure there was no shoulder-surfing involved.
So the takeaway here is that you will potentially have to deal with two different locations of to the system same registration data, that might for whatever reason differ, and decide which one to use in a way that's safe both to your system, as well as the end user that's registering. This might prove pretty tricky to do properly, so I'd advise against it.
Instead, rather make sure your registration form is served via HTTPS, and then simply fill the password field back, as it was last entered on user's POST request and if it satisfies your constraints, even if some of the other input fields are filled in incorrectly and the form needs reposting.
-
My current implementation does not put user's POST password back into the input field, so it will be empty by default unless I use some method to store the password. With regards to the social engineering attack scenario, I think @mgibsonbr made a very good point about clearing the sessionStorage upon successful registration. Anyway, if the victim is so trusting to give the attacker access to his/her computer, wouldn't a keylogger do the same to get the password? I am not quite sure what the security community thinks of resending plain text password using HTTPS. Any comment from others? Thanks Commented Jun 5, 2013 at 6:55
-
@QuestionOverflow - I didn't want to repeat previous poster's points, but I agree there's quite some valid arguments in that answer. What I wanted to add is, that the way you propose your model can provide for a really convenient and simple to exploit vulnerability. And we all know what we say about the opportunity and thieves. My description of possible events might be a bit less imaginative than some attackers might think of, though. As for the other part, it's been discussed before. Read all the answers there tho, for added perspective ;) Commented Jun 5, 2013 at 7:09
I'd use some intertab communication to distribute the password instead of storing the password in any persistent storage (cookie, localstorage, etc. there are countless solutions, check evercookie). This way the password will live in the browser until you close the last tab for the actual domain.
You can do intertab communication safely with BroadcastChannel
or SharedWorker
or postMessage
probably there are other methods I don't know of, they are always reinventing the wheel. The first two sends the messages to every tab, the last one sends only to tabs opened from the same parent tab, so it is somewhat restrictive, but supported by more browsers.
If you store your passwords in js memory, you need to prevent XSS with special headers. And ofc. you need to check the displayed content for HTML tags and you need always JSON encode the data you want to directly inject into javascript as variable.
TildalWave's post is interesting, I think these methods are not vulnerable to that, because the sync is almost instant and you can sync login, logout, etc. too.
If you decide to use localstorage anyways, it is better to use a signed userid, timeout and salt instead of the password itself. You can send the credentials to the server, which can verify them, and send the data with the signature back. They can be stored in a cookie or whatever persistent storage you want. These tokens are sometimes used by REST APIs if there is a browser client, because this solution is stateless and still gives a sensation of having a classic session. Sometimes they sign every request, not just the user id to enhance security.