Opened 7 years ago

Closed 5 years ago

#4709 closed defect (fixed)

Hash passwords on server for lobby

Reported by: rugk Owned by:
Priority: Must Have Milestone: Alpha 23
Component: Multiplayer lobby Keywords:
Cc: Victor ADASCALITEI Patch:

Description

We have to talk about passwords here. First, just assume, that passwords are worth to protect. They are not only for a game, they may be reused by users (although they should not, but not everyone cares for that) or may be of some other interest. So just assume this. You would not need to hash them on the client anyway, if you have not thought they are worth protecting. So no need to argue about this.

Secondly some basics about password hashing:

  1. Why do we hash?

Because an attacker, who get's the password hash, should have to use CPU/GPU power to reverse the hash and get the original password or even do not get it at all.

  1. What is a salt?

A salt is appended the the plaintext password before passed through the hashing function. The salt should be unique per password, in order to increase the attackers effort even more.

In "more or less" pseudo-code that's how you use a salt: hash(password + salt) --> hashedpassword, salt --> into DB

So, more information on how to properly hash password in https://crackstation.net/hashing-security.htm. It's a really easy explanation, so it is worth a read! Basically it also explains everything I do here, but I use the short version here. If anything is unclear, please first read the links I add.


Now I see you already hash the password one the client and that is totally fine! It protects against local attackers getting to know the real password of the user. However, now I come and say you: That's not enough. You should hash your password on the server. Important: I do not say, abandon the hash on the client. I just say, also hash it on the server. In effect, you should hash it two times. So, then, why?

First, let's make a concrete attack/threat model for this case. Actually this attack model is the same what all websites with password login nowadays have and thus they (should) employ exactly the same mechanisms as described here. So "0ad lobby server" can be seen as equivalent for "web server" and "browser" equivalent for "0ad application".

Our threat model is: Server compromise. Because if the server is compromised and user passwords would be in plain-text, an attacker could just use the passwords to login to the service or even any other service, where the user used the same password.

Side note: There are many real world examples of this attack. Servers get breached from time to time.

So, now you say, but you already hash the password. So the attacker needs to crack it anyway. That's right, but now let's get some expert opinion from the article I linked previously:

Even if you are hashing the user's passwords [on the client], you still have to hash the hashes on the server. Consider a website [here: server] that hashes users' passwords in the user's browser without hashing the hashes on the server. To authenticate a user, this website will accept a hash from the browser and check if that hash exactly matches the one in the database. This seems more secure than just hashing on the server, since the users' passwords are never sent to the server, but it's not.

The problem is that the client-side hash logically becomes the user's password. All the user needs to do to authenticate is tell the server the hash of their password. If a bad guy got a user's hash they could use it to authenticate to the server, without knowing the user's password! So, if the bad guy somehow steals the database of hashes from this hypothetical website, they'll have immediate access to everyone's accounts without having to guess any passwords.

If this is not explanation to you read the whole (!) answer on Stackexchange: https://security.stackexchange.com/questions/53594/why-is-client-side-hashing-of-a-password-so-uncommon#53606

Now another thing:

  1. Yes, please salt your password on your server. As I explained, that is important.
  2. And use a secure password hash, at least PBKDF2. bcrypt, scrypt or even – the latest thing – Argon2 may be used.

So once we finished this, just let me say that every cryptographer or serious infosec people will suggest you exactly the same. If you do not believe, ask one…


Now how to implement this… First the good news: This does not need a client update**

What you do is this:

  1. You first make your implementation ready, including hash algorithm and such things.
  2. You then hash all the currently saved (hashes of) passwords. (This may take and some time and obviously prevent some users temporarily from logging in)
  3. Now change the login algorithm/system on the server to use your new system and hash your passwords on the server.

That's it! No fallback possible, as the passwords are now all hashed on the server. And clients just sent their password to the server as usually.

Change History (3)

comment:1 by Victor ADASCALITEI, 6 years ago

Cc: Victor ADASCALITEI added

comment:2 by elexis, 6 years ago

Not storing the password but only the hash means that in the worst case an attacker has to capture each login to get the hashed password instead of being able to download the entire database of hashed passwords that could be used to login, so it has value for sure.

It also means that there is no way to recover a forgotton password, but that is (a) not needed if it could be reset and (b) we could only recover the password hash, which isn't quite right if we wanted that feature. So I agree it's the better alternative.

However there is nothing to implement here because we don't implement the serverside code of lobby authentication.

This is ejabberd which is an XMPP server. So either ejabberd and the XMPP specs already support it and we don't have to implement anything, or they don't then it would have to be implemented upstream.

XMPP and ejabberd do support it, so we have to configure it only: https://docs.ejabberd.im/admin/configuration/#internal

comment:3 by elexis, 5 years ago

Milestone: BacklogAlpha 23
Resolution: fixed
Status: newclosed

As reported by user1:

When the lobby server was updated by Itms more than a year ago, the database was changed to use SCRAM, so neither lobby admins nor attackers can obtain the (previously only clientside-hashed) passwords anymore.

https://docs.ejabberd.im/admin/configuration/#internal

Note: See TracTickets for help on using tickets.