36

Say I had a database that looked like this:

Name   Password hash (bcrypt)                                          Status
--------------------------------------------------------------------------------
Dave   $2y$10SyyWTpNB.TyWd3nM hQ41frOtObcircAb3nJw1Cf9dC6CT7tVIEb6XS   Standard
Sarah  $2y$10$fUJrNA200sXgWUJAP7XEiuq4itHa43Y8QVIpc/YWscgVJ PYWbLLV.   Admin
Mike   $2y$10$01jx7u7hnfKOzBYyjNWskOPQ23w1Cf1gNiv42wsKqXKOf8filzS02    Standard 

If an attacker gained access to this database, then they would immediately see that Sarah is an admin, and would probably focus on breaking that password, so they could have more power. Is there any way I could somehow hide whether or not someone is an admin in the database so that an attacker would not know who the admins are? I could simply hash the value (standard or admin) but that would only give 1 bit of entropy, and I would hope to get a bit more security than that.

  • 118
    An attacker could also simply look at the oldest entry. In most systems this will be the admin account :) – Mikescher May 2 '17 at 12:06
  • 4
    It would be simpler and you'd be better off to add 1 bit of entropy to the password (hash), effectively doubling the average effort of a successful brute force attack, than to deprive the attacker of 1 bit of reconnaissance information. Also, it doesn't take that much longer to brute-force a pre-image for 1 million hashes than it takes for a single one (assuming equal actual pre-image entropy). – David Foerster May 2 '17 at 16:20
  • 2
    @kasperd: You make a good point about password entropy which I considered but left out for the sake of brevity and the following reasonable assumption: the admin password will have a much higher entropy than the average account password and will likely be among the last ones to be found during a typical dictionary attack that tries short passwords before longer passwords and common words before less common words before random character sequences. – David Foerster May 2 '17 at 21:12
  • 2
    @JonasDralle Attacker may have acquired the hashes from a leaked backup. The admins might have used the same password for more than one system. – kasperd May 3 '17 at 7:19
  • 24
    If the attacker can scan your database you already have a much bigger problem than this. – user207421 May 3 '17 at 10:55
127

I would say this is a bit too much trouble considering what you get out of it. I think when the attacker has access to the database you have way bigger problems. Obfuscating the admin status of a user will just cost the attacker some extra time, but an APT (Advanced Persistent Threat) would probably not be deterred by this fact.

  • 70
    Exactly. Obfuscating the admin status is as useless as trying to tape your belongings to the floor so burglars can't get it - they still can and will do it. You want to prevent the burglar from entering instead. – James Cameron May 2 '17 at 10:04
  • 12
    @JamesCameron unless your 'belongings' consist of 10 inch nails. Then, I think the burglar might just wonder what is wrong with you... and report you as insane. – The Great Duck May 2 '17 at 22:07
  • 22
    @TheGreatDuck - whereas nine-inch-nails would of course be perfectly reasonable. – Simba May 3 '17 at 12:12
  • 6
    @TheGreatDuck: I tell my wife they are 10" nails, but they are really only 8.5" nails. – Pieter Geerkens May 3 '17 at 20:26
  • 6
    @PieterGeerkens: And that is why she cannot parallel park. – dotancohen May 4 '17 at 9:02
26

Security through obfuscation has limited effectiveness at best - to determine if it is suitable, you need to understand what threats you want to counter. If a threat actor can read your database directly, what benefit is there in hiding a particular stored detail?

If there is benefit in obfuscation (make sure you can really prove this), then employ the type of obfuscation that addresses that threat (encrypted values, off-line data sources, hashing, etc.).

5

I agree with Black Magic that it's probably not worth doing, but if you wanted you could use a key derivation function to make an encryption key based on the password, and use that to encrypt the content of the Status column.

Potentially the status would have to be kept in memory for any open user sessions, so those could still be vulnerable to the attacker.

This would mean you would have the same restrictions as your attacker, assuming you don't know your users passwords. You wouldn't be able to read status from the DB, and if you wanted to change a user status you would have to change their password at the same time.

  • 1
    Actually you could change a status to non-admin without knowing the password - just enter some random value in the field and rely on the practically zero probability that that could happen to match the ciphertext for 'admin'. The code that reads it would have to tolerate unexpected values. – bdsl May 3 '17 at 12:44
  • Or you could have a 'newStatus' db column and set that instead, in plaintext, then clear it when the user logs in and you update the encrypted status. – bdsl May 3 '17 at 12:45
  • 6
    It also means you can't have a password recovery feature without losing the status of the account. – a CVn May 3 '17 at 15:27
  • 1
    Good point @MichaelKjörling that would probably be a deal breaker. – bdsl May 3 '17 at 15:47
3

Many modern systems actually do separate the user's login (how they authenticate) from their "profiles" (permissions they have), implemented as two or more discrete systems. Your login server could just have a GUID, a hashed username, and hashed password; on a successful login, transfer the session to the application server. As long as your application server isn't compromised, the login database is useless even if it gets dumped.

As an added step, you could also encrypt the user's data with a key from the login server (stored as part of the session), making the application server more secure as well. Two systems is typically harder to defeat than one. However, if you're not willing to set up two servers (or clusters), and it all sounds like too much work, then you're probably better off with your current design anyways. Simply knowing which accounts to target doesn't make the job any easier; if the attacker can crack one, then they can crack all of them with parallel computing.

2

The suggestion from PlasmaHH was to : "prepend a letter to the password when hashed (actually multiple letters, it was a "group id") and have the authentication mechanism try out all combinations."

Though it is somewhat security by obscurity, and needs to be paired with good practice like :

  • a strong work factor on bcrypt
  • admins having a strong password
  • ways to prevent the attacker from having a copy of the database in the first place

It is a good way to slow down an attacker enough so that the password is changed before it is found.

Cracking one non trivial password (assuming you used a strong work factor) may take a few days to a few months, so it is doable, but if they don't know which account is worth hacking, it makes them have to hack each account.

So unless they are lucky, or you named an admin account "admin", they will have to try multiple accounts, that will make their costs at least an order of magnitude bigger, making the attacker either wait more, buy more power, or give up.

In conclusion, it is not worthless, as it is a cheap deterrent that doesn't bother the user.

Note that if you have hints of someone being an admin, like a post from someone else edited by them (if only admins can do that), masking their status in the db is useless.

As others have mentioned, this has gotchas like preventing you from making an user admin without changing or at least asking for his password.

If available, requesting 2 factor authentication for admins would probably be a better way to secure admin accounts.

2

Yes you can. Just add the admin status as part of the password.

like: HereIsMe!65371 = admin HereIsMe!65370 = regular

Then at login, try regular first then admin, like this:

if (sha512($password . "0") eq $hash) {
blabla user functions
} else {
if (sha512($password . "1") eq $hash) {
blabla admin functions
}
else
{
show incorrect password message
}
}

IMPORTANT: Make sure you ensure somebody cannot edit their last char of their own password. Eg, make sure registration form, forgot password form, and change password form, always append a 0 or 1 at the end of the password depending on their real status. Store the status in a server-side session, preferable encrypted using a client-side session cookie.

This makes it practically impossible to deduce the admin status without successfully cracking the password.

  • 1
    knowing the scheme and looking for 1's breaks your system - if you have a separate table listing who the admins are, why not use that instead of mangling passwords? and then if you have this table, how do you protect it from being read along with the mentioned table in the question? – schroeder May 4 '17 at 14:04
  • also, this is very similar to satibel's answer – schroeder May 4 '17 at 14:05
  • 1
    @schroeder Its neccessary to add 0 to users, else you run into risk that the user add 1 to their password and become admins. By hardcoding the admin hash, you can deduce the admin by looking at code + db. But with my idea, you cannot deduce who is admin, even with access to both. You can try cracking the password and check if 0 or 1 matches the hash. – sebastian nielsen May 4 '17 at 21:19
  • 1
    @schroeder What is not scalable about the solution? You can extend this to as many permissions as you want, even allowing for bitflags. It's rather fragile and has some disadvantages but it solves the given problem. – Voo May 4 '17 at 21:22
  • 1
    Another problem with solutions like this is it becomes difficult to implement an interface for higher level admins to revoke admin status from other users who become problematic on the fly, since any sane implementation of this would store only the admin status itself in the session data on login and thus couldn't check roles on every relevant request, and so revoking admin access requires forcefully deleting login session data so that the user has to log in again. – Jason C May 5 '17 at 3:47
0

If your database supports it setup a LDAP or similar authentication server, and then the credentials won't be stored locally.

  • The question is about hiding authorisation, not authentication - and making that queryable from a remote source can make it worse if not implemented correctly (the authorisation info need only be accessible on successfull authentication!) – rackandboneman May 4 '17 at 21:54
  • @rackandboneman The server in question will have no credentials on the server, so they will be hidden. If you have your own network, and you make your authentication server visible to the internet you deserve to be hacked. Obviously you have to use TLS 2048 bits or more and blah blah or whatever it allows. – cybernard May 4 '17 at 23:09
0

There are several interesting technical suggestions here, but it needs to be mentioned that even if you implement them perfectly this approach will quite literally gain you nothing in the event of an intrusion for the following reasons:

  • If someone has database access (though sql injection or something like that), it's a given that they can pretty much do whatever they want on your server with the permissions of whatever user your database service is running under since most database management systems provide functionality for manipulating files and running processes on their host. That means the intruder can modify your web pages or server-side processing to capture plaintext passwords during login and very quickly gain unencrypted passwords for your active users. I'm assuming your administrator account is an active user.
  • If someone gains access to your password hashes, they are probably not going to dial in on which ones they should attempt to crack first. They'll just run a bulk cracker to process all of them at once and in each pass it will check against all of the hashes in the table they are processing.
  • Even if you kept your admin password hash in a separate table or outside of the database entirely, the compromise of less privileged accounts will likely lead to privilege escalation as long as the intrusion has gone undetected since the intruder will be able to impersonate trusted users to gain access to more information (by using a moderator account to talk with the admin and kick off cookie stealing or some other malicious activity, for instance).
  • If your site has any social capabilities it's very likely that it already exposes other ways to identify administrative users.
-4

If the attacker gained access to the database, then they can just make their own bcrypt hash and replace the one in the database. There's no need to crack the hash.

  • 14
    Not if they only had read access, or e.g. a data dump or something. – Jason C May 2 '17 at 15:27
  • 2
    Also - even if they do have write access, it wouldn't help them to insert random bcrypt hashes into the database. They would have to understand the cryptography of the authorization system in order for it to accept the hashes, and if they can do that, then they can just decrypt the existing hashes much more easily. – Kernel Stearns May 2 '17 at 15:29
  • 3
    Does not answer the question. Even if what you propose is true, the attacker would have to know which one to replace. – schroeder May 2 '17 at 16:33
  • 2
    @Schroeder He can replace all the hashes in the table (if he has write access) So I think this is a valid answer to the question. – Ajay Brahmakshatriya May 3 '17 at 8:55
  • 3
    @AjayBrahmakshatriya only if the attacker wants to announce himself so loudly. If the attacker wants to be more tactical (and quiet), knowing which account to target is important. So, no, this answer bypasses and dismisses the question, it does not answer it. – schroeder May 3 '17 at 9:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.