Creating a more secure login form

I’ve been thinking about the way normal login forms work. Normally a user is shown a login page, enters his username and password, submits the form, upon which the back-end of the code hashes the password, and see if a user exists with the given username and the hashed password. This works relatively well, but my problem with it is that when the user posts his credentials, they are submitted over the internet in plain text, making it very vulnerable to a Man in the middle attack (given the site is not using SSL).

So I thought about it some more, and came up with a scheme that I think prevents the man in the middle attack without the need for SSL.

The outline of this scheme is as follows:

  1. The user enters the login page. On the login page a random key is requested from the back-end, let’s call it secret_key. This is put in a hidden field on the login form. The back-end remembers the key it generated for the form in a session.
  2. The users fills in his username and password and submits the form
  3. Upon submit, a javascript function is fired that hashes the users password (using md5,sha1,any one-way hashing function really) concatenates it with secret_key, and hashes the concatenation again. So what you get is

key = hash(hash(password)+secret_key)

Then the javascript replaces the password field with as zeroes (as much zeroes as the user entered characters, as to not confuse him that the password appears to be changing).
Then the form is submitted.
4) The backend receives the username and the key, and can then request the record from the database with the given username, hash the password associated with that user, concatenate secret_key, which it also knows as it was the back-end that generated and stored it in a session in the first place, and then hash it again.
So, as the server already knows the hash of the password and secret_key, it can determine

key2 = hash(hashed-password-from-db + secret_key)

If key equals key2, the user entered the correct password and is logged in.

If this fails you would also need to check the normal way as described in the first paragraph of this post, for those who have javascript disabled.

As far as I can see there is no way for the man in the middle to repeat this request because secret_key changes every time the login page is shown, and he has now way of recovering the entered password from the key (given a strong enough one-way hashing function of course).

What do you think, would this method work? Are there any pitfalls?

I would never ever rely on my method for processing CC’s.
I would always use SSL when processing CC’s.

Nope, this would cause “Pwnage” meaning the middleman has the control and the real user now lost complete control…meaning they can’t even log out!!! Once the middleman gets the right session id and returns w/ new one…then for real user… hahahahha… it’ll be a bad day for him.

Also, I’m more worry about user spying on my information then manipulating it. If they did manipulate or create new transactions it may get audit it and catch this *******. If he somehow gets your SSN,Address,Personal Info… = credit card opportunites. I read some story that a hacker did this to some user and created a credit card. Problem is that this hacker did not purchase anything for himself… he tortured the victim by purchasing $20000 of stuff to victim’s home… each day the victim was receiving various items. This would be anyone’s nightmare.

The ONLY way to prevent a man in the middle attack is to use SSL.

You can’t use JavaScript because some of your users will have it disabled or not available so anything you do with JavaScript just provides a second way for the man in the middle to break in making it easier for them.

That’s true! I haven’t thought of that.
Well, at least the man in the middle can this way only see information of the user, but has no way of manipulating it (when he’s not hijacking the session).

With regard to session hijacking, do you think refreshing/renewing the session id on every request / every n requests (if random(0,n)==1) would help prevent that (at least to some extent)?

Actually, why would the middlemen try to hack ur password when the response from the server is in plain text. He’d probably say “Oh silly programmer~” and print out your personal info.

That’s just for authentication but what about hiding your session id? The middle man won’t know or even care what your password is. He’ll just hijack your session id from your HTTP header. This is the reason why HTTPS site always remain HTTPS. If it was used just for “authentication”, you would just have initial HTTPS and rest would be HTTP. But, what you’re doing is essentially what SSL do and I can tell you gave it a lot of thought!

Why won’t my code prevent a man in the middle attack (session hijacking and users/browsers with javascript disabled aside) ?

That’s why I said:

So yes, those with javascript disabled don’t have any advantage of my scheme, but also no disadvantage.