9

I for some reason am not understanding how to execute a secure authentication between client and server for a user. I've read many resources, and I understand how to use the hashing and salting tools, but not getting the final picture.

The user logs in from a mobile application which sends a request to a server. Here is my understanding:

  1. The goal is to send the user's password to the server for authentication, but it is not to be sent cleartext. Generate a unique random salt for every login. Now, send the following two items to the server:

    • hash(salt + password)
    • salt
  2. On the server side, ...ok this is where I'm totally confused. What the heck do I do here? How should the password in the database be stored - hash(password)? And the salt is stored separately? How do I verify the password? Who should be generating the salt - the server or the client? It's a messy nightmare!

Update

After reading the answers, it makes more sense now. I will be using SSL, but I just wanted to know how it would work without it. Now the question is, where do session ids tie in to this?

A. Say when a user logs in and is authenticated, the server creates a new random session id and this session id is saved in the table for that user and is sent back to the client and saved there. For every subsequent request the user makes, instead of sending a password over every time, I send the session id and make sure it matches the session id in the user's account. Do I need to do any hashing or encryption on this, or is it just as basic as sending over the cleartext session id and checking if it matches?

B. And this is another very common sense question to you guys, but say I have a POST url that does some things, and requires certain fields such as userId = self.request.get('userId'). This value is assigned by my client when sending the request. The question is, can an attacker generate their own request to that URL and fill in their own values for userId in that request, and have the request go through? I'm not really sure how that works..

2 Answers 2

9

In your title you are talking about basic authentication, I assume you are talking about HTTP basic authentication, which is when the browser prompts you for a password, encode and sends over the wire. However, you do not really control the mechanisms and encryptions with that method. It's also generally not used because its less secure and you can't add things like SALTs, one time pins, captchas, etc.

Likely, you want to implement form based authentication using an HTML form which sends the form data with POST. You should secure the submission of this form using SSL/TLS with a certificate for general public usage. This helps to limit the ability for man in the middle (MiTM) attacks where an attacker can eavesdrop and capture the username and passwords. You can do encryption on the client side using JavaScript, but you still need the initial password stored up front. I have seen this implementation on only a few pen tests, but its not very common to do it with JavaScript like that.

Now, in regards to salting and hashing, and everything like that. This is more to do with the storage of the credentials in the database. Typically, you receive the password without encryption through the SSL-secured form submission. You don't want to store the actual password in your database, so you hash it and you salt it using your hash algorithm (e.g., bcrypt). The salt+hash make it so you can store the password without it being directly stored. Hashes are one way so unless you use a technique called rainbow tables, you would have to brute force every possibility until you ran through the algorithm and got the same result. Using a salt make it more difficult to use rainbow tables because the rainbow table must take into account the salt and cannot just be the "standard" rainbow table.

You can have a per user salt or one you use universally, a per-user salt would be more secure. In your user table in your database you would store the following

  1. the username
  2. the hash(salt+password)
  3. the salt for this user

Now, when a user comes to log in again they submit their username and password in the form. You then want to see if they are in the table so you then:

  1. Look up the supplied username in your database and return the hash and the salt
  2. Take the provided username and rerun the hashing function using the salt obtained in 1 to do somehting like hash(salt+password submit on form)
  3. If the hash generated in 2, matches the on retrieved from the database in 1 then you know they provided the correct password

The whole point is to not store the actual password and to make it computational expensive to figure out what this random set of characters maps back to (i.e., difficult to determine the real password).

Some further reading

Update OP Asks about not sending through SSL:

You need to accomplish to separate things here: (1) secure data in transit and (2) secure data at rest. What we talked about with hashes accomplishes securing at rest. To secure it in transit, you need to ensure the data going over the network is encrypted somehow. It sounds like you don't want to obtain or cannot obtain a SSL certificate. This is generally the most common way. Otherwise you could implement a much more complex programatic way, where you have your own private and public keys. You more or less encrypt the data before its sent with your private key using a JavaScript implementation of PGP or similar. This is not recommend because you can easily mess it up and it requires JavaScript, which your users may not have enabled. You still use the salting as described above, you just encrypt at the client with your public key and then decrypt on the server end with your private key, then continue as if it was transfered with SSL.

Algorithm (caveat - requires JavaScript or other client side language enbaled)

  1. Create a log in form, do not set a submit action in the form - we don't want the information sent through normal means because its confidential and we are not using SSL
  2. Create a JavaScript handler which is used to submit the form, as part of the processing, encrypt the password field with your private key, then submit it using HTTP post.
  3. Once received on the server, decrypt with public key
  4. You have now transfered the actual password over the network with encryption
  5. Change you private-public key pair frequently to reduce compromise or reversing.
  6. Continue with securing at rest as detailed above.

Update 2 OP continues question to know more about securing session variables:

It's always best to put all submission over SSL to protect eavesdropping. Even if you hash all of your cookie data, if I can intercept and I just need to send you back the hash, well, I already have it if I can be MiTM. You should use multiple factors to limit session hijacking and CSRF attacks. Rather than going into deep detail here, you may want to check out the OWASP Top 10 and read through the various security concerns and how to mitigate. OWASP is one of the top resources for learning how to secure web apps.

The second question you are asking is if your server side app is doing logic basic on a user id being passed can this be faked? Yes, use session management to determine the current user, don't let the client tell you who they are after authentication.

This article, also related to the questions you ask and may be useful for you.

6
  • Ok makes sense. I guess the part I'm not understanding is the actual sending of the password over the air during the form submission process. Say I'm not using SSL - what then? How would I send the password to the server for authentication?
    – Snowman
    Aug 30, 2012 at 23:10
  • Ya I actually read that tutorial, still didn't make sense to me the overall process. I'm starting to understand it a little better now, but now the question is what if I'm not using SSL?
    – Snowman
    Aug 30, 2012 at 23:17
  • Thanks for your detailed answer. I'll actually be using SSL but I just wanted to know how it would work without it to better understand the system. Can you take a look at my updated question and see what other details you can help fill in?
    – Snowman
    Aug 30, 2012 at 23:43
  • What about sending both a user id and session id - I get the user based on the supplied user id; if the user.sessionId == incoming_session_id, then I know its the user. Is this ok? Or should I not send the user id at all, and just send the session id, and do a query on my table to get the user with incoming_session_id. I'd rather do the first approach since I don't have session_id indexed..
    – Snowman
    Aug 30, 2012 at 23:55
  • 1
    @mohabitar At this point, I think you may want to start a new question instead of introducing sub questions. I also highly recommend reading through the OWASP top 10 and other references on the OWASP site to understand session management. I would also recommend not building your own authentication system and session management system from scratch, there are some good and vetted solutions out there for almost all main-stream platforms. You should never have to send the user id, the session should know who the user is, and you should never trust anything sent from the client side.
    – Eric G
    Aug 31, 2012 at 0:02
6

Authentication over plain HTTP (not HTTPS) is rarely appropriate. Indeed, what is authentication ? It is a guarantee that some commands really come from who they claim to. A server granting access is a server which will accept GET and POST commands and respond to them, e.g. by sending confidential documents back. If you worry about a evil eavesdropper, who spies on the sent password, then you should worry about the very same evil eavesdropper, who can spy over the server response, i.e. directly looking at the confidential documents themselves. "'Vast the password, I'll commandeer the data itself", says the pirate.

Therefore, for most practical security models, you need an actual protection system for the data itself. There is a widely used protocol for that, and it is called SSL (HTTPS when used to wrap around HTTP). SSL not only protects the transferred data, it also authenticates the server: through validation of the server certificate, the client is sure that it talks to the right server. In that situation, the client can send the password "as is" through the SSL tunnel: since it is transferred under the Aegis of SSL, the password is not at risk.

If you do not use SSL, then your authentication efforts will come to naught in practical attack scenarios.

You would still want to use hashing and salting, but on the server, not on the client. This is a mitigation measure, to lower the risk that a serious breach becomes catastrophic (see this blog post for a detailed discussion). Since it is only for storage, server-side, the client needs not be aware of how it is done, and the communication protocol is not impacted.

Edit: to clarify: you need to do hashes or whatnots on the client only to protect against bad people doing bad things on the link, e.g. spying on what is sent or modifying that which is sent. By using HTTP and not HTTPS, you are already assuming that this does not happen (or, if you do not assume, you are in for a cruel disillusion at some point). Therefore, there is no need to hash anything on the client.

1
  • Thanks for your answer. Do you think you can clear up some more confusion for me - I've updated the question with a few more details..
    – Snowman
    Aug 30, 2012 at 23:42

You must log in to answer this question.

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