Andrew/Ron(Savage),
I appreciate both of your feedback! Many of the concerns you've pointed out are the exact ones I want to address. I think that https: with SSL/TLS is probably the first and foremost step to safeguard, secondly, using some form of hashed password. I'm always interested in ideas and methods.

Thanks very much!


Andrew Baumhauer wrote:

louis gonzales wrote:

Hello Dist,
What are some best practices on an initial form taking a PW/ID from a user to login. Right now one method which seems to be really unsecured, is to take them, check them against the PW/ID stored in the database and permit/deny against that. And for passing this info - or a token - between pages, using URL via the URI path and/or using hidden 'post'ed variables.

Anyone who would like to email me offline on details, you're welcomed.

Thanks In Advance,

Well, this is a very complex topic! I have spent considerable time working out a solution that appears secure.

There are several decisions you must make up front:

How does the the database store passwords? Either plaintext, encrypted, or hashed. Plaintext or known key encrypted allows the program to automatically email passwords to end users -- who always forget their passwords. Hashed keys are one way, and are useless to intruders other than to verify that the password hashed by the client code (javascript) = the database password. If the password is encrypted, where are the keys? If a hacker can look at the server code, they can find the key, and decrypt every password. This is important to realize if you are going to store sensitive information (ie national id numbers, credit card, etc). Encryption is only strong if the key is protected.

The next problem you need to deal with is state tracking. After a user authenticates, how do you track them from page to page (keep them "logged in"?

Your choices determine what you can do, and the limitations you will face.

Here's the solution I use for http:// style access to web enabled database apps. I assume the connection is prone to sniffing. I assume that users will forget passwords. Passwords are reset to random values, and emailed to the address I've collected at account creation.

Upon first connect to website, Apache sets unique session cookie (as defined in httpd.conf) which we'll call SC for short

   Apache2 config:
       # User tracking cookies
       CookieTracking on
       CookieName SC
       CookieDomain .domain.com
       CookieStyle Cookie
       CookieExpires "8 hours"

The use is not logged in at this point. Next, the use clicks something that asks for a usename and password, be it a form, or some AJAXy thing. The client javascript code takes the password and MD5 sums it, and sends that as the password along with the cleartext username. The MD5 javascript code can be found online. The dojo.crypto.md5 code works as well, but be aware that you may have to strip off the "==" at the end of the string at the server side code.

On the server, the code receives two ARGS, the username and password. Here's where you can go two ways, depending on how paranoid you are. If the web app can read the user credentials table (that you built), all you need to do is retrieve the stored password hash (you are using MD5 to store passwords), and see if they match. If they do, the user knows the correct password.

Another approach is to MD5 sum the SC, and the password on the client, and not trust the web app account to access passwords stored in the database. Use a stored procedure with definer rights to create a function that takes the hashed password concatenation from the client, the current session key from the apache request object, and returns true or false if the database computed hash matches. In this case, you can store the passwords in plaintext. The stored procedure(s) that the web application use to access the user table prevent the password from ever being disclosed to the application, even though they aren't encrypted.

Assuming that the user authenticated, now you need to track this user as "logged in". Create two new cookies. One cookie is the record id of the user in the database, let's call this ID. The second cookie is used to protect against someone setting a "logged in" ID cookie to any value they wish. This cookie is formed as follows. Take the ID value, SC, browser string, and first two octets of the IP address A.B (from A.B.C.D), along with a long 32 character secret string that only the application knows. Hash this string using SHAxxx and store the result in the in a key called MAC or something.

Now, for each page that a user visits, if there's an ID and MAC cookie, take the ID, SC, browser string, A.B, and your secret and compute the MAC. If the user provided MAC matches, then you know that the ID is valid, and you can use that as a primary key for looking up user privileges.

This method works through proxies, since the IP address of multiple proxies is unlikely to change the first two octets of the client IP (if it does in your case, drop the A.B from computing the MAC).


I have another case where user passwords are stored in LDAP. Therefore, I need the plaintext password from the user. The only solution I have found is to use https:// to send the data. This worked for me, since most of the data in the database was personal to begin with. A solution to not use https (SSL) would be public key encryption. I haven't found a good implementation of PKE in javascript for the client as of yet. PKE is needed, because you can't safely send the encryption key to the client, since the channel you send it is insecure.

Hope this helps.

Andrew Baumhauer
n-Capture Consulting



--
Email:    [EMAIL PROTECTED]
WebSite:  http://www.linuxlouis.net
"Open the pod bay doors HAL!" -2001: A Space Odyssey
"Good morning starshine, the Earth says hello." -Willy Wonka

Reply via email to