0

Question

I was just brainstorming about the hashing, stretching, salting part of the user password in the authentication process and I want it to be as secure as possible (no matter how paranoid that is).

I came up with something that I described in the diagram shown below. I was wondering if this is a good way to go or that is has some disadvantages or potential risks using this process.

Diagram

I think the combination of salting and stretching locally based on a pin-code that is never stored but just known by the user makes it harder to guess the salt and also to reproduce the exact process without the user since the local used salt and amount of stretching will be unknown to the server.

Secondly assuming that the connection is compromised because of an MiTM attack. The process of how the leaked hash of the password is created is still unknown because the salt and iterations (based on the pincode) are unknown. The local process (in the browser) can be reversed engineered obviously but assuming the browser and computer aren't infected, just by intercepting the communication, it's not possible to reproduce it (read: very hard to guess).

Simplified example

- User opens browser and goes to login page
- User types password / pincode / username, nothing gets send yet
- Javascript in browser uses pincode to generate a salt
- Generated salt is used to hash the password locally
- Only username and hashed (+salted+stretched) password is send to server over compromised TLS SSL
- Server rehashes the browser created hash with a server-wide/global salt to +restretch
- Server rehashes previous hash with a user-specific salt so the same salt isn't used for all stored password hashes
- Final hash is used for storage / comparing in authentication process
- User is send to a Two-Factor authentication step
Bob Ortiz
  • 6,339
  • 9
  • 45
  • 91
  • 2
    What problem are you trying to solve? What attack(s) is this intended to protect against? – Anders Jun 23 '16 at 12:14
  • Also could you write this as some kind of simple pseudo code as well? I find it hard to follow all the boxes. – Anders Jun 23 '16 at 12:18
  • 1
    @Anders both done. – Bob Ortiz Jun 23 '16 at 12:26
  • This might help in passive MitM, not against active MitM. But why aren't you using some sort of standardized mechanism to prevent passive MitM attacks? How will the server validate the hash when the user tries to authenticate without transferring the pincode? I think you should also explain the authentication process. – Silver Jun 23 '16 at 12:37
  • @Silver, can you suggest an answer wherein you describe why it does help in a passive but not in an active MitM attack? The server will validate the hash because the exact same local/server-side process is used when creating the password the very first time. The auth. process is nothing more than validating the username/hash like described above and after that sending the user to a TFA page. Also, what standardized mechanism do you suggest? – Bob Ortiz Jun 23 '16 at 12:41
  • 1. Active MitM, I inject my JavaScript code to obtain both password and pin. 2. If the server validates the hash, then actually the hash becomes the password (an attacker can send the hash if it can capture it via passive attacks). – Silver Jun 23 '16 at 12:44
  • @Silver, in case of a javascript injection there is nothing you can protect against. So lets exclude that. But "the hash becomes the password" is interesting. This is partly true but the hash that is locally created and the hash that is server-side stored are different. So you can only send the local hash as the server expects it before rehashing it. Right? – Bob Ortiz Jun 23 '16 at 12:47
  • See also: the ["Is this scheme secure" anti-pattern](http://meta.security.stackexchange.com/a/2394/2113) canonical answer. – Jacco Jun 23 '16 at 12:52
  • Indeed, see my answer which I will update based on your comments to provide an overview. – Silver Jun 23 '16 at 12:54
  • Also, JavaScript crypto is generally [not seen as desirable](https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/). – Jacco Jun 23 '16 at 12:54

2 Answers2

5

Hashing client side

Secondly assuming that the connection is compromised because of an MiTM attack. The process of how the leaked hash of the password is created is still unknown because the salt and iterations (based on the pincode) are unknown.

In case of a MitM attack (made possible by say incorrect use of TLS) hashing client side will not help you. The attacker could just modify the JavaScript sent to the client so that it sends the password and PIN in clear text. Short of having the user read and verify the complete JavaScript code at every login there is no way to protect your password if an attacker breakes the TLS.

Using a PIN that is "never stored"

I think the combination of salting and stretching locally based on a pin-code that is never stored but just known by the user makes it harder to guess the salt and also to reproduce the exact process without the user since the local used salt and amount of stretching will be unknown to the server.

If I understand you correctly, your goal is to make it harder to make an offline brute force attack on the password hashes, by using a salt that is never stored.

Let me recap the main points of your scheme to establish some terminology. We have a hash function: HASH(data, salt, itteration count). The user has secrets P1 (password) and P2 (PIN). P2 is hashed locally with N itterations and using P2 as salt: H1 = HASH(P1, P2, N). H2 is sent to the server, where it hashed again (with a user specific salt and M itterations) : H2 = HASH(H1, salt, M).

So how would an attacker in posession of H2 brute force this? She would just use a normal dictionary attack, looping through possible combinations of P1 and P2. First she would recreate the process on the client to get H1 and then she would recreate the process on the server to get H2, and compare it with the actual value to see if she picket the right secrets.

This would take N + M itterations per attempt, and she would have to make X ^ (LENGTH(P1) + LENGTH(P2)) (where X is the size of the alphabet) attempts to try all possible secrets.

Now compare this to a scheme where there would just be one password with the combined length of P1 and P2, that is only hashed on the server with N + M itterations. Would your scheme be any better than this? No, it would be exactly the same. That would also take N + M itterations per attempt, and X ^ (LENGTH(P1) + LENGTH(P2)) attempts in total.

Long story short, your scheme is no better than just using a longer password. The only difference is that you have split the password in two parts, complicated things a bit, and done some hashing on the client.

Or in more general terms: You can not increase security by doing something with the password client side. If you do F(P) and send that instead of P, the attacker will also do F(P) when she brute force and you have gained nothing.

Some thoughts about rolling your own

You are rolling your own here - that is, you are coming up with your own solution to a problem where an established best practice already exists. This has been discussed here many times before:

Rolling your own system when there are established solutiongs seldom leads anywhere. You add more complexity, but you seldom add any security. If you are lucky, at least you don't make things worse. But if you are unlucky, there is no limit to the problems you can cause for yourself.

In your case, I don't think you did any fatal mistakes leading to obvious vulnerabilities. But who knows? Not me, not you. And when you implement this complex system, there are so many more places where you can make a tiny mistake and ruin it.

That said, speculating about alternative solutions can be a very useful learning experience and help us understand existing practices and concepts better. So there is nothing wrong in proposing and discussing different systems, as long as you don't roll them out into production.

Anders
  • 65,052
  • 24
  • 180
  • 218
1

The local hashing will not help against passive MitM if the authentication process is simply sending the hash to the server. The attacker can capture the hash during registration/password change and just send a request with the hash instead of using your web application which computes the hash based on password and pin code.

Server side hashing keeps serving the same purpose, protecting passwords in case of DB breach. I believe it serves no MitM protection? Explain how if you believe it does protect in any way against MitM.

Nothing keeps the attacker from crafting his own messages.

An attack would look like:

  • Sniff the hash from victim when sent from browser to server during registration.
  • Sniff a message sent when authenticating to see it's structure and identify the location of the hash
  • Create you own message and use the username and hash obtained in the first step.

Just deploy your application over SSL and you are safe from MitM attacks.

Silver
  • 1,820
  • 12
  • 23
  • server-side hashing is indeed for protecting after a breach. The local hashing is for protecting in case of a MiTM. – Bob Ortiz Jun 23 '16 at 13:01
  • Yes, but as described by me and the other answer, this local hashing doesn't help you. If you can clearly state the security requirements I can try looking for standards that have a been proven to be secure to fill these requirements. – Silver Jun 23 '16 at 13:30