in reply to Re^2: CGI::Session not "storing" anything
in thread CGI::Session not "storing" anything
The reason I do the $CGI->param(...) || undef is exactly for the case where the parameters are zero or empty. Those values are "replaced" by undef which the DBI "quote" turns into "NULL". Very few columns in my database tables allow NULL values.
Well, I would add a short comment to the code, explaining that trick (it really looks like a bug). Simply because my future self could get very angry spending hours to debug such tricks, invent a time machine, return back in time to now, and hurt me. ;-)
Actually I do NOT store passwords in plain text. The password strings that pass through here were encoded in the browser's javascript before being sent to this app. I am comparing encoded strings, not plain text. The code I am writing will perhaps be used in other locations once I am done and I can not absolutely force future clients to use SSL connections so I encrypt what i can and assume a non-SSL'd channel.
Sorry, but that won't help much. Your login form transmits an email address and an encrypted (that's what I read from your term "encoded") password back to the server. Together with the usual IP, TCP and HTTP headers, that should easily fit into a single package. Easy to grab, easy to decode. Essentially a no-brainer with Firesheep or Wireshark. I don't even have to break your Javascript-based encryption. It is sufficient to re-transmit the encrypted password (http://en.wikipedia.org/wiki/Replay_attack), because it is identical for every login until the user changes his password.
Even if you would protect the remainder of the login mechanism against replay attacks, all I need to to with a grabbed pair of email address plus encrypted password is to fill in both into the login form I get when I want to log in into your service. Firebug can easily be used to modify the form on-the-fly in a way that it transmits the encrypted password as pasted into the form.
This "solution" offers only a tiny bit more security than a plain-text password. Your site is vulnerable, but until the attacker can decrypt the password, the attacker can not use it on other sites.
Unfortunately, your encryption function was transmitted before, when the user's browser loaded the login form and the associated Javascript code. So if you really encrypt the password (instead of processing it through a hash function), you have handed out the encryption algorithm and the encryption key to the attacker. And that's a very bad idea, because now the attacker has all components he need to calculate the plaintext password.
If you really just encoded the password (instead of encrypting or hashing it), like for example by transfering it to its base64, base36, hex, or URL representation, things become dramatically easier for the attacker, because he just has to change the encoding back, no crypto involved at all.
If you can't use SSL, think about Challenge-response authentication, but be aware that you need to protect the shared secret (password or password hash) with that.
A Zero-knowledge password proof looks really promising, but I don't know if it can be easily implemented in a HTTP context.
Perhaps it is easier to rely on SSL to protect the plain text password transfered through the SSL layer, and to use salted hashes in the database.
Alexander
|
|---|