I'm looking at a web application that does something I find very unusual in the handling of login sessions.

The application hashes the password with SHA256 and salt and saves it either in session storage or in local storage in the browser (depending on if the user wants to stay logged in permanently). It also uses a proper hashing for passwords again on the server side (PBKDF2) and the application is served via HTTPS.

This approach seems more dangerous than storing a random value for identifying a user session, but I have some trouble to think of ways to attack this that actually pose a serious danger. There is the potential that someone that gets access to this value could brute force the password, but an attacker that gets to that point can already cause serious damage and probably get the password in other ways as well. To convince people to change this I probably need better arguments than this.

What specific disadvantages has this approach compared to the typical approaches for session storage?

  • 1
    The impact of an XSS attack becomes much more severe. If a session key gets compromised, it's only valid until that session expires. If the hashed password gets compromised and cracked, it will allow an attacker to access the account until the user changes his or her password (unless 2FA is enabled). It could also allow the user to be compromised in other ways, if their password is shared across other services. Commented May 21, 2018 at 18:33
  • I don't think it's that bad because you should be able to trust your application environment anyway. If you have a compromise that can read LS, it can reach anything else. There's some merit to "don't store important documents at home, it could be broken into", but at the end of the day, you have to trust something, and if your app is otherwise secure, why not trust your app? Validate on the server still...
    – dandavis
    Commented May 21, 2018 at 19:11
  • 2
    I don't understand, is the SHA256-hashed password sent to the server and hashed again, or is the plaintext password sent? Also, are some of the values sent on every request? Commented May 21, 2018 at 20:00
  • @multithr3at3d the hashed password is sent to the server and hashed there again for storage.
    – user837487
    Commented May 21, 2018 at 20:08
  • 1
    Honestly, the more concerning aspect of this question is that the developer behind this site used some kind of "roll your own" security, which could indicate many more problems down the line.
    – BgrWorker
    Commented May 22, 2018 at 15:35

4 Answers 4


It's really dangerous.

The use of the local storage to store session identifiers is never recommended as the data is always accessible by JavaScript.

Please use Cookies to mitigate this risk using the httpOnly flag.

A single XSS (Cross Site Scripting) attack will be able to steal all the data in these objects and/or load malicious information, so don't consider the "local storage" to be trusted and less for a session identifier/hashed password.

Ref: https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Local_Storage

  • would this assessment change if it was possible to add a restrictive content security policy to the entire application? As far as I understand, this would prevent essentially all conventional XSS attacks.
    – user837487
    Commented May 21, 2018 at 19:57
  • Check this rdegges.com/2018/please-stop-using-local-storage, the note at the very end. Maybe a mix with the "Subresource Integrity" can be secure. Just do not implement it this way if you can avoid it.
    – jmingov
    Commented May 21, 2018 at 20:03
  • This isn't right, down voting. The browser uses a same-origin policy to prevent cross domain I/O of the DOM, cookies and HTML5 storage mechanisms.
    – jas-
    Commented May 24, 2018 at 15:51
  • If XSS exists, the attacker can essentially navigating the sites on behalf of the users. It will make httpOnly vain. Commented Jul 4, 2023 at 0:35
  • What about JWTs being stored in localstorage then? Isn't it very dangerous as well?
    – parsecer
    Commented Jan 23 at 21:14

There are several issues with this.

First, the salted SHA-256 value is a password-equivalent; any attacker who gets access to that value can simply pass it directly to the server to authenticate. No need to brute-force the hash.

Second, using local storage instead of a cookie flagged with httpOnly means that this password-equivalent value is potentially vulnerable to being stolen by XSS attacks. Any script running on your site has full access to this data.

And third, a single round of SHA-256 is a bad choice for password hashing, as it can be brute-forced relatively easily. It's entirely possible that any attacker who manages to get a hold of the hash will brute-force it to obtain the user's password then use that password to attack the user's accounts on other sites (assuming the user reuses passwords between sites, which unfortunately is pretty common).


Dangerous. Not recommended.

Some reasons why;

  1. MITM attacks. In the event of a side channel attack, a cipher downgrade, padding or weaknesses in the encryption algorithm sending a hashed password across the line can be brute forced once acquired.

  2. Nefarious/vulnerable browser plugins. There are thousands of custom plugins running on your clients browsers. Some of these are designed to do bad things while others have historically proven insecure leading to additional information stealing from the browser.

  3. DOM rebinding & XSS attacks. Weaknesses in the client code can assist attackers in stealing credentials stored in the browser.

  4. Vulnerabilities in the browser. Here a vulnerable browser can also lead to theft of credentials. Typically useful for session replay attack types.

Some ways to protect your clients;


  2. Wrap your code delivery in a TLS connection with strong ciphers and nothing older than v1.2. This requires strong keys, ECC/RSA greater than 2048 bits, nothing less than an SHA512 algorithm for the x509 certificates.

  3. Configure your application to enforce strong security by using the content-security-header options.

  4. Ensure your application isn't leaking sensitive data or if developing use an identifier to ensure nothing sensitive leaves the server.

  5. Keep your server patched and applications up to date including firmware.


This approach is strictly less secure than storing a standard session token/cookie and sending the password in plain text.

First of all, the client-hashed password works as a password replacement, so the security effect on the server side is irrelevant. In case of a server data breach, the only thing this client-side hashing will prevent is the attacker seeing your original password, which should already be random and unique by using a password manager. An attacker will still be able to authenticate as you by directly sending the hashed password to the server.

If this was the only problem, it would be as secure as a standard authentication + random unique password, but since the hashed password is stored in local memory, it also increases the chance of the password leaking. Any simple attack that accesses the local storage will give away your hashed password, which can now be used to login (see my first point).

Third, a single round of SHA256 is not secure at all. Any determined attacker will break a medium length password in a very short time, and there isn't even any security through obscurity since javascript code is visible to anyone having access to the website, meaning an attacker won't even have to find what algorithm was used and how many rounds were performed.

For more informations on why client-side hashing is a bad/superfluous idea, see this: Client side password hashing

In the end, the most concerning thing is that those developers are following a non-standard approach, and this would make me think twice before using their website.

  • What about JWTs being stored in localstorage then? Isn't it very dangerous as well?
    – parsecer
    Commented Jan 23 at 21:22

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .