Hashing Passwords for a Web Login

Which prevents the password from ever being transmitted or being stored by the server.

Given how many thefts of passwords still happen that seems a good idea …

Nope. I wrote that it is a quote. I didn’t use quote tags so it is visible in total.

But I added some “Gänsefüsschen” to make it clearer :wink:

The logic is “if your server is compromised, you’ve already lost.” If they can intercept the raw password, they can intercept your hashed password, and that’s still enough. It’s still password-equivalent.

[quote=436813:@Markus Winter]Which prevents the password from ever being transmitted or being stored by the server.

Given how many thefts of passwords still happen that seems a good idea …[/quote]
Not necessarily. And besides, if you’re already using PBKDF2, we’re talking about running a hash over thousands of iterations. Is the one extra hash on the client really going to make a difference?

I’d go so far as to say doing it client-side makes it less secure because you can’t do sanity checking on the server. The user could input a single character password, or use one of the most common passwords, or use one previously listed on haveibeenpwned. So you write a bunch of javascript to prevent all that too, and have to use creative methods like k-anonymity to perform the checking securely.

Or… you just do the industry standard method. It works, if done correctly. It’s when people who are not security researchers try to outsmart it that leaks happen.

Unless Thom has a later/better article that I’ve missed:
https://thezaz.com/blog/storing_passwords_securely_wit

There’s also this article, though it deals more with algorithms than with the design pattern Thom describes above. You can use some of the newer algorithms with Xojo (see below):
https://latacora.micro.blog/2018/04/03/cryptographic-right-answers.html#asymmetric-signatures

There’s a libsodium wrapper for Xojo on Git:
https://github.com/lbmonsalve/Xojo-libsodium

Note: I’m not going to say you have to use the newer algorithms in libsodium at this time. If you use what’s in Xojo’s Crypto correctly you will have secure password storage. But newer algorithms do exist to make hacking even more difficult. For that reason it would be nice to see libsodium wrapped into the Xojo framework.

Well, there’s actionable code based on that article: GitHub - thommcgrath/AuthenticationKit: Provides "Security Through Obesity" password storage and TOTP to Xojo projects.

Xojo currently uses Crypto++, a “competing” library to libsodium. There’s little reason for them to switch. If there is crypto functionality you need, lookup how to do it with Crypto++ and propose an API using a Feedback request. That’s how nearly everything (or maybe everything) made it into Xojo’s Crypto module in the first place. It’s “relatively” simple for them to write wrappers for the Crypto++ library, but impractical for them to do everything, so tell them what you need and what problem it solves, and there’s a reasonable chance it’ll get implemented.

Edit: deleting this post because it’s incorrect. What was going through my brain was “hash” even though I was typing “salt.” That’s what I get for posting after a marathon session trying to fix a server last night.

It’s not a Xojo flaw. Assuming properly implemented https the compromise would have to be an active “listener” at the server. In other words, active malicious code. That’s a problem for everyone because as Thom has pointed out if your server is compromised in that respect…

If he’s got the salt and the nonce that were transmitted he can attack the hash. Worse, in that solution the hashes (edit) are linked to users which means he can run attacks against the entire user list.

Properly implemented salts/hashes make password recovery incredibly difficult for someone who manages to obtain your data but not compromise your actual running code.

That’s not to say you can just ignore the possibility of attacks which compromise your running server application (as opposed to just obtaining database data). But I think the best defense there is securing your server.

I’ll add this since it’s related to the type of attack you’re worried about: There’s yet another side channel attack which allows code running on an Intel processor to obtain data from other threads of execution regardless of privilege level, virtual machines, etc. Patches are being pushed now, but to fully mitigate the attack requires disabling hyper threading at a huge performance loss.

Attacks like this are why I still push server hardware over cloud for some clients and use scenarios.

FYI The master repo is at GitHub - charonn0/RB-libsodium: A Realbasic and Xojo binding to libsodium :slight_smile:

There is a technique for accomplishing what you want, but it’s not simple or easy. I’ve not implemented it myself, but it might be worth a look. https://en.m.wikipedia.org/wiki/Secure_Remote_Password_protocol

Thinking and reading more about this…real passwords being transmitted over https can still potentially leak via one of the following attacks, even if they are otherwise stored properly in the database.

  • Client malware. Not much you can do about this in terms of preventing the leak (2FA can help prevent an account compromise).
  • A SSL downgrade, compromise, or MITM attack.
  • Server malware.
  • Server side-channel attack. This is distinct from server malware because it can be executed in many ways against a VPS, and there’s the risk that someone could find a way to execute it against real server hardware as well. In other words, it doesn’t have to be “installed” and cannot be detected.

Hashing the password before sending it to the server, and then storing it using the pattern described and coded by Thom McGrath, does offer a little more protection against some of the above. Notes:

  • I’m considering simple client side hashing, not SRP (which is really interesting).
  • If you do this, the hash becomes the password as far as your server is concerned (as was pointed out above). And you would want to treat it as a password, i.e. salted hash of a hash before storing it in the database.
  • The Stack Overflow solution links users and password table hashes which you do not want to do. So you can’t employ that directly.

So does client side hashing solve anything?

  • Client side hashing doesn’t really help with MITM because the JavaScript can be altered at the mid-point. But it would help if SSL is compromised in some other fashion allowing transmissions to be read but not altered. Any exchanged salt and iteration count would be known as well, so you don’t want to reuse your storage salt/count. But by using a user-specific transmission salt/count you’ve still increased the cost of a rainbow table attack to discover the real password, just not any where near as much as if the salt/iteration count were not known.

  • In the event of a server compromise, it does not prevent an attacker from using the password hash to login to the user’s account on your server. Again, as far as your server is concerned the hash is the password. But it would add an extra layer against real password discovery, preventing use against other accounts the user may have. A very strong layer in the event that the password hash is leaked but not the transmission salt/count (i.e. in a side channel attack).

I think I have to back track my original response (which is the standard response) that SSL handles this and if your server is compromised you’re in trouble any way. This has been sitting on my mind in large part because of side channel attacks like the one just published. With a VPS your server doesn’t have to be compromised to leak data. Any other VPS, or layer in the hardware stack underneath the virtual server instances, can be compromised and leak your data. There’s also transmission and it’s not a 100% guarantee that SSL/TLS/your certificate won’t be compromised. Client side hashing isn’t standard practice, but maybe it should be.

Note that I don’t consider this a Xojo Web weakness because most frameworks out there assume client side hashing is pointless and transmit real passwords over SSL.

1 Like

Thom: I had run into the SRP thing, too, but it was to difficult for me to understand and so I didn’t look into it.

Daniel: Good summary, thanks.

Took me a while to get the first part. But I was planning to hash it again on the server regardless (more out of a feeling, before the explanation came from Thom)

Yes, I realized that after I posted this, but I was already in bed (my head still spinning).

Overall, thanks for all the good input.

I accept that the hashing is difficult do to on the frontent, and so I’m not doing it in my app. Instead, I generate random pws for the users and they cannot even change them, meaning a leaked pw of theirs won’t harm them on other sites beause they cannot use their favorite one.

One question remains unanswered, though: Does typing in a password field send the key strokes over to the server? Brief looks into the framwork.js code suggest that if often checks whether an event handler is implemented, e.g. I saw that in the listbox code. But I have neither looked at the password entry code yet nor am even sure that this check really checks for whether the event is implemented on the server or is some other kind of check.

May I interrupt for a moment?

This idea is very bad. As Thom said. Once the server or db is compromised…

Don’t put your energy too much into passwords. Let your clients better have a 2nd factor with one-time passwords (e.g. RFC 6238). This corresponds to the current security standards.

@Tomas Jakobs ,

Please explain why giving users a password is worse than letting them choose a bad one? After all, this way I can assure that password meets my entropy needs. The plain password is still not saved on the server, of course, but is hashed with PBKDF2.

Our application needs to know the users. Only known users get access, and WE know them individually, and therefore we have to authorize their access. Hence we know their login names (we designate them, too, using an anonymized code). This is not an open system.

Ah, I guess you mean that the process of transmitting the password to them is unsafe? That’s not an issue in our (i.e. the company I do this for) case because we have a safe and approved method of transmitting the pw to them already. If that procees could be compromized, though, I see your point of needing a one-time auth token and letting them choose their own private pw then.

And the damage to a server-break-in will only lead to us losing revenue because we cannot be assured any more that the logged users did truly use our service. So, it’s our loss, not the customer’s (of whom we do not store any personal data other than that they talked to our server, and when). With not even using a personal password of their choosing, there’s nothing that could harm the customer in case we have a break-in, therefore.

On the topic of using 2FA - can you suggest a service that’s Europe based and that we could use in small volumes (i.e. not more than a dozen calls per day for now)? After all, this requires a second pathway, such as sending SMS. Maybe Google Authenticator? Though, that’s US based, right? Might be a problem.

Thinking the other way around, would you trust a prefabricated password sent to you via the Internet?

Yes transmitting and more using. I generally assume that passwords will be compromised sooner or later. Either by auto-fill function in browsers, proxies or MITM … a nosy colleague who looks over your shoulder or the greasy track on a touch display.

This is where the 2nd factor helps, if implemented and used properly (not on the same device).

I don’t see why not if it’s:

  • From the site I’m creating an account on.
  • Sent via https.
  • Random (as best as I can tell) and not in any way dependent on my personal information.

The end user’s concern when registering a new account and re-using a password is: what if this site has nefarious actors and/or leaks my password and someone can get on another account? If the new account comes with a new random password then that hole is closed. I suppose the secondary risk is that someone within the organization could use my password, i.e. it’s stored in plain text or captured. But that’s a risk with a password I submit as well.

2FA is the answer to many password/security issues.

2FA is a band-aid to combat password reuse. And just like password storage, can be done poorly, such as using SMS. Any account with a truly random unique password will gain nothing from having a second random secret attached.

This isn’t to say 2FA is bad. I’m in full support of it, because users will reuse passwords. But in my experience, those people reusing passwords usually won’t setup 2FA.

1 Like

The advantage is in having a second channel. Assume a truly random, unique password properly stored on the server. If the client is compromised, or if the server is compromised in a way that it’s not fully controlled but passwords can be read while being hashed, then the attacker can gain access to the account. The attacker can’t reuse the username and password to access your Facebook or your Gmail, but who cares if it’s your bank account they now have access to?

2FA means even if your PC or your bank’s server is compromised the attacker still can’t necessarily access your account. Given the growing importance of side-channel attacks I think it’s a very good additional layer of security even for those of us who use truly random, unique passwords every where.

[quote=437183:@Daniel Taylor]The advantage is in having a second channel. Assume a truly random, unique password properly stored on the server. If the client is compromised, or if the server is compromised in a way that it’s not fully controlled but passwords can be read while being hashed, then the attacker can gain access to the account. The attacker can’t reuse the username and password to access your Facebook or your Gmail, but who cares if it’s your bank account they now have access to?

2FA means even if your PC or your bank’s server is compromised the attacker still can’t necessarily access your account. Given the growing importance of side-channel attacks I think it’s a very good additional layer of security even for those of us who use truly random, unique passwords every where.[/quote]
If your password or hash is compromised, then your secret is too. The secret can’t be hashed, it has to be stored in a retrievable way. So you have to assume the attacker will get the secret when they get the rest of the account data.

Not if the 2FA secret is on a different client device. As to the server…

In a side-channel attack they may not be able to get the rest of the account data. You can have a sever that’s not fully compromised and not remotely controlled yet still leaking some data. 2FA is not a 100% guarantee, but it is another barrier.

Because people will still find this when doing a web search (I did), I’d like to include the following to summarise why a lot of what has been mentioned here is dangerous or pointless.

The premise of this post, which is that “only the user should know their password”, is flawed. It should be “only the user should remember their password”.

Why you HAVE to use SSL
Client side encryption of passwords is only ever a good idea if “current best minimum https standard” (gonna refer to it as SSL) is absolutely not possible, and even then is dangerous and almost pointless.

SSL does not ONLY encrypt the data sent between you and the webserver, it AUTHENTICATES the web server at the same time. While domain authenticated SSL certificates are not foolproof, they are still good enough for most things. If you are not using SSL (or are using a self-signed cert) then your client has no way of knowing that they are connecting to YOUR server, and not an attacker pretending to be you. HTTP is trivial to intercept and compromise, and DNS hijacks are also remarkably easy to pull off.

Without SSL, an attacker can craft a fake website identical to yours and remove any javascript that encrypts the password on the client side, and the client will likely never know. They could change the javascript to use reversible encryption so that a packet sniffer sees an encrypted password, but the attacker can decrypt it.

SSL with browser encrypted passwords
If your web session is ENCRYPTED and AUTHENTICATED using SSL, then you have to ask why you would want additional browser side encryption (SSL is, after all, a way of securing the data you send to the server).

A password is a type of authentication / encryption called a “shared secret”. The important word to consider here is “shared” - it’s shared between the actor authenticating and the actor seeking authentication. You CAN NOT change that. Even if you use a hardened / trusted / third party authentication provider, the actor actually doing the authentication will need to know your password. (Of course, if you are authenticating using something other than a username / password this is not necessarily true, but this comment is specifically about username / password auth).

Here is another thing - if you do not trust the website with your password, why do you trust them with your data? The server can generally access, manipulate and share your data without your password, and only requires that you authenticate so that it knows it can trust YOU. If the server is untrustworthy, or compromised in any way, your data is probably already effectively compromised.

How most servers actually authenticate you using your username and password
Pretty much all servers store your username and password in their database. The username is almost always plain text, while the password is (unless the site is completely incompetent) stored in some sort of (preferably salted) hash.

When you enter a username + password, the server hashes your password as needed, then looks up your username and compares the hashed password it just calculated with the hashed password it has stored. If the passwords match, you are considered authenticated.

If a website hashes the password before sending it to the server, the server can compare the browser-hashed password with the database password to authenticate you, but the hashed password will STILL be sent down the same channel as the actual password would, so anyone who can see the password can see the hash, and they could then fake a login by sending the hash without knowing what the password was.

Of course, if server asks you to hash the hash with a temporary salt, and then compares the result with the db password hashed with the same temp salt, then the person intercepting the data will not know the password. But then again, if the SSL encryption has been broken in a way that an attacker can view the encrypted data transfer, it’s reasonable to assume that they could modify the stream as well, and could gain access to your password by crafting a web page that gives them access to your password.

What about servers that use the password to decrypt my data?
Some servers (Lastpass claims to do this) sends the strongly encrypted data to the browser without decrypting it on their side, and the browser decrypts the data on it’s side without tranmitting a password (not quite, but close enough). But even here, if the server is unstrustorthy / compromised, how would you know it’s not sending the password / unencrypted data back to the attackers?

Most people wouldn’t know how to check. Most people who know how to check don’t (at least not all the time).

Again, if the server is untrustworthy or compromised, you’re screwed.

What about 2FA?
A lot has been said about 2FA. 2FA stands for Two Factor Authentication and here is the lowdown: Two factor authentication means using two factors (sources) of authentication - a password and one time text string (OTP - One Time Password) sms’d to you, or emailed to you, or generated by an encryption device.

The point of 2FA is that an attacker has to compromise 2 ‘authentication sources’ to be successful. This means that email based 2FA is almost useless (if your PC mail client gets the otp, since compromising your PC gives your browser password via a keylogger and your email OTP); and key based 2FA that is not accessible via your PC in any way is the most secure. It’s FAR harder to compromise the PC AND Phone than to just compromise one or the other. It’s virtually impossible to compromise a 2FA fob or similar.

Not all 2FA solutions are equal. Not all are terribly secure. Most improve security even when badly implemented (NOTE: If the 2FA is allowed to authenticate on it’s own then it’s no longer 2FA and what I’ve said no longer applies) (NOTE 2: This statement is only true if existing password implementations are sane and secure - using 2FA to improve a bad password doesn’t work).

Of course, if the server is untrustworthy or compromised, all bets are off…

Summary

  1. You need to trust the server you are connecting to, and for the most part that is what SSL does - it tells YOU that the server is who it says it is (or at least that it is who it’s domain name says it is).
  2. Most servers do not need your password to access your data. Your username and password are there to tell the server that the person behind the keyboard is you. Anything that hides your username / password combo from the server in any meaningful way stops the server from authenticating you and is pointless.
  3. If you really don’t want to send a password to the server, look at using user certificates for authentication. Just be sure to understand the implications, as well as recognise that the server STILL has to have a way to authenticate you.

PROBABLY THE MOST IMPORTANT THING TO TAKE AWAY FROM THIS IS THAT BAD SECURITY IS WORSE THAN NO SECURITY, AND SECURITY IS DIFFICULT TO DO RIGHT! FOLLOW BEST PRACTICES AND DON’T TRY TO DO YOUR OWN THING UNLESS YOU REALLY REALLY ARE QUALIFIED TO DO SO.

Final note: This is a long reply, and is meant to provide food for thought rather than security guidelines.

5 Likes