Question

What is the best way to handle user account management in a system, without having your employees who have access to a database, to have access to the accounts.

Examples:

  1. Storing username/password in the database. This is a bad idea because anyone that has access to a database can see the username and password. And hence use it.

  2. Storing username/password hash. This is a better method, but the account can be accessed by replacing the password hash in the database with the hash of another account that you know the auth info for. Then after access is granted reverting it back in the database.

How does windows/*nix handle this?

Was it helpful?

Solution

This was a common issue in UNIX many years ago, and was resolved by separating the user identity components (username, UID, shell, full name, etc.) from the authentication components (password hash, password hash salt). The identity components can be globally readable (and in fact must be, if UIDs are to be mapped to usernames), but the authentication components must be kept inaccessible to users. To authenticate a user, have a trusted system which will accept a username and password, and will return a simple result of "authenticated" or "not authenticated". This system should be the only application with access to the authentication database, and should wait for a random amount of time (perhaps between 0.1 and 3 seconds) before replying to help avoid timing attacks.

OTHER TIPS

This is a better method, but the account can be accessed by replacing the password hash in the database with the hash of another account that you know the auth info for.

There's really no way around this. Anyone who as write access to the password file has complete control of the computer.

I'd go with 2 but use some salt. Some pseudocode:

SetPassword(user, password)
    salt = RandomString()
    hash = Hashfunction(salt+password)
    StoreInDatabase(user, salt, hash)

CheckPassword(user, password)
    (salt, hash) = GetFromDatabase(user)
    if Hashfunction(salt+password) == hash
        return "Success"
    else
        return "Login Failed"

It is important to use a well known hash function (such as MD5 or SHA-1), implemented in a library. Don't roll your own or try implementing it from a book its just not worth the risk of getting it wrong.

@Brian R. Bondy: The reason you use salt is to make dictionary attaks harder, the attacker can't hash a dictionary and try against all the passwords, instead she have to take the salt + the dictionary and hash it, which makes the storage requierments expode. If you have a dictionary of the 1000 most commaon passwords and hash them you need something like 16 kB but if you add two random letters you get 62*62*16 kB ≈ 62 Mb.

Else you could use some kind of One-time passwords I have heard good things about OTPW but havent used it.

Jeff Atwood has some good posts concerning hashing, if you decide to go that route:

You could use openID and save no confidential user passwords at all. Who said it is for websites only?

  1. A very bad idea indeed. If the database is compromised, all accounts are compromised.
  2. Good way to go. If your hash algorithm includes the username, replacing the password hash with another one will not work.

Unix stores hashes in a a text file /etc/shadow, which is accessible only to privileged users. Passwords are encrypted with a salt.

You could store the salt for the hashed password in another table, of course each user would have their own salt. You could then limit access to that table.

The usual approach is to use option two with email:

Store user name, password hash and email address into the database.

Users can either input their password or reset it, in the latter case a random password is generated, a new hash is created for the user and the password is sent to him via email.

Edit: If the database is compromised then you can only guarantee no sensible information can be accessed, you can no longer ensure the security of your application.

Hash the username and the password together. That way, if two users have the same password, the hashes will still be different.

This is a bit of a non problem for a lot of applications because gaining access to the database is probably the most common goal of any attacker. So if they already have access to the database why would they still want to login to the application ? :)

If the 'system' is a public website RPX can provide you with a login/user account services for the most common providers, like OpenId, Facebook, Google, etc.

Now, given the way you formulate your question I guess the 'system' you're talking about is more likely an internal windows/linux based enterprise app. Nevertheless; for those googling around for login/user account providers (like I did before a came across RPX), this could be a good fit :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top