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