17 comments

[ 4.1 ms ] story [ 37.0 ms ] thread
Securing the login is hard. Facebook submits to an SSL page but I suspect the rest of the time their persistent login cookie is free to snatch.
A couple issues to note off the top of my head:

  "In order to login, a user will be presented with a 
   standard html form on a page that may or may not be 
   encrypted, at this point SSL is not relevant."
SSL is -quite- relevant at this point. You are specifically addressing MITM situations, and an MITM can, if you do not use SSL to send the log in form, send a modified login form which either posts to a different attacker-controlled server or simply attempts to post to your server in the clear, allowing the attacker to capture the users credentials in cleartext.

Also, it seems that after you use the SSL session to get the AES-encrypted cookies to the user, the user still has to have an AES key stored on their system (and the AES key is what allows the user to continue making requests by proving the user's knowledge thereof by encrypting randomly generated "hashes" and getting new AES keys). What would prevent an MITM attacker, once you are no longer using SSL, from sending down a modified page to the user with malicious javascript that sends the user's current AES key to the attacker, thereby allowing the attacker to hijack the user's session?

While this scheme -should- prevent offline/passive replay attacks, it does not seem to mitigate an active Man-In-The-Middle attack.

ADD: What I would suggest if you could not afford to run your site in full-SSL, is that you require SSL for any operation that is not a READ or is a read of sensitive account info. Don't allow a user to post messages, delete records, etc. over regular HTTP. If some MITM steals your users cookies, then they will at best be able to, say, read a bit more of your user's mail than they would have been able to had they just sniffed the portion that your user actually requested. (Not that I would ever recommend not using full-SSL for email. Remember "Forgot your password?") Also, do not give a "Remember this computer forever" option when not using full-SSL (or at least make the "forever" cookie a secure cookie and still expire the non-secure session cookie) and ALWAYS expire cookies on the server side.

I suspect that the writer didn't mean MITM, but rather a passive eavesdropper.

More significantly, this doesn't actually prevent replay attacks either. There are essentially two "cookies" (I'm oversimplifying) - long term, and single session cookies. If you catch the single session cookie, you can use it until it expires, at least according to the writeup.

To protect against only a passive eavesdropper if you aren't worried about replay or MITM you only need to do the authentication over SSL (What the writer lists as #2 in the list of "normal ways" of handling the problem at the top of the post). And no, it does not prevent replay of short-term session cookies; It seems to only allow for the long-term "cookie" (which is never sent in cleartext. It isn't an actual browser "cookie") (the mentioned "Persistent Storage") to be used to generate more than one short-term cookie, even without SSL (though with as many SQL hits that it is proposed it would be doing it probably wouldn't perform any better, which is pretty much the point). So you're fine if your short-term session expires by the time your passive eavesdropper cares to try to use the intercepted data.
SSL is relevant and in my actual implementation, which I am prepping now, I do use SSL on the login form, but technically, the form it is submitting to needs to be SSL, but the form itself does not.

Since I wrote the article I have made some small adjustments to the AES key dialogue, they key is generated at the login form using javascript then sent as an ssl cookie to the authentication form and also stored into a local persistent storage, which is not accessible (barring an exploit.) Once the auth page is reached the aes and guid cookies are cleared. I suppose that a script could be crafted to cause the user to reveal the key and guid stored in persistent storage, this is something I am still working on securing against.

I will consider your suggestions carefully and attempt to integrate them as I work to code this out.

I have posted this discussion into the comments in the article and will be updating it tonight to reflect this conversation. Thank You.

the form it is submitting to needs to be SSL, but the form itself does not

then how do you guarantee the form is going to submit to an SSL-protected resource? the form and all of your javascript has to be sent over SSL, otherwise any of it can be tampered with to simply bypass your logic and post the form contents to an unencrypted resource.

if you haven't already seen it, watch moxie's blackhat presentation about ssl:

https://www.blackhat.com/html/bh-dc-09/bh-dc-09-archives.htm...

That seems like viable thought. I will watch the presentation when I get a chance, but for now I will modify the article to consider this scenario and my code already forces SSL on the login page and the authentication script.
You're right -- but do you expect users to View Source to confirm its posting to an SSL url? How else would they be able to tell if a MITM altered the form to post somewhere insecure?
What problem exactly are you trying to solve? Do you have an actual site in hand that you can't afford to run SSL on, but also can't afford to toss a couple of CPUs at? That's an awfully narrow window given how cheap CPU is now, and it's only getting narrower. Add to that the intrinsic diceyness of trying to build your own cryptographic system and it sure seems unlikely this is a win of any kind.
If your document isn't printable, you should provide a printable version. Unlike me, not all users will fiddle with Firebug and Print Preview for a few minutes.
the password is hashed with sha1 so that the database does not need to store the actual password

This recommended approach is not good security practice for password storage. If the database is compromised, your passwords are vulnerable to rainbow table attacks. See http://en.wikipedia.org/wiki/Rainbow_table

ya I should probably being using HMAC
Passwords always should be salted. (meaning a -different- nonce for each password) This prevents rainbow tables from being useful. Instead of a raw hash function, you should (for maximum security) be using something specifically designed to be expensive: read pbkdf2, bcrypt, scrypt; This will make even dictionary attacks very difficult. If someone has cracked your db they also probably also have access to your HMAC key, at which point cracking can still be parallellized and is not significantly slowed.
Is there a reference implementation that you like and that is well documented.
(comment deleted)