11

This question already has an answer here:

I wonder which of these things is more secure.

Imagine hard coded credentials, similar to this:

if user.Equals("registereduser") && (password.Equals(encryptedpassword))
{
    Give access to the user

I know this method has big flaws like having to modify the code each time you want to add a new user, and being only usable for a few people that are using the application. But if you know you're just going to have a bunch of people to use it, and that's hardly gonna change, it's not that horrible.

I assume that compiled code is impossible to decompile in reasonable time, and an attacker is not going to look for hard coded passwords in the first place.

Is it more secure to hard code credentials like this? Or is it more secure to use the common method of having the password encrypted in a database?

marked as duplicate by D.W., schroeder, Mark, Xander, Steve Jun 27 '15 at 18:44

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 4
    You may think that an attacker wouldn't believe that the password is stored in code, but he's still going to look at the code to find the database table where the password hashes are stored, so he'll still find it. This is another case of security through obscurity -- don't count on the fact that you're "different" to help protect you, there's plenty of code out there with hard-coded passwords, so no attacker will be surprised to find it in your code. – Johnny Jun 26 '15 at 20:12
  • 1
    Credentials must be easy to change. If you are using any credentials which cannot be easily changed, then that is a vulnerability. You can improve security slightly by combining one salt common to all users stored in the code with a unique salt per password stored in the database. But as soon as you deviate even the slightest from standard practices, you run the risk of introducing a vulnerability. This risk is even higher if you do not fully understand the security reasons behind the standard practices. – kasperd Jun 27 '15 at 11:16
  • Credentials to what ? – Overmind Feb 26 at 10:51
26

A few points:

What you mean with encrypting passwords in the DB is hashing. That´s a big big difference.

The first reason why DBs are used instead of hard coding user data is not security, but simplicity
(add/modify/delete users without recompiling etc.)

Storing passwords in plaintext is a problem, doesn't matter if they are in your program or in the DB. Store them hashed and salted (DB and/or program doesn't matter. hash them).

Relying that an attacker won´t expect that your user data is in your program is "security by obscurity" and generally not secure.

Getting strings from a compiled program is far more easy than you think. Without any obfuscation like in your example, it takes not even a minute (and this includes starting an editor and searching manually for the strings). And who says that your program is compiled at all? Eg. PHP...

Don't try to change established practices if you don't understand the reasons behind it.

  • Sorry, I think I didn't explain one thing properly, I was giving as a fact that compiled code would be ofuscated, in fact,for example, I've checked the ASP.NET languages compile into dlls and seems too hard to get any data from there (I'm not an expert, but it gives me that feeling). – user3421 Jun 26 '15 at 13:43
  • 13
    .NET languages are very easy to decompile, that´s just how the are. Ther are several programs available to do so. Without obfuscating, one just can read the passwords from the source after that. A normal obfuscator won´t scramble all strings, so it doens´t change the fact. And an "extreme" obfuscator, other than making your program slower, will only make the code harder to read, but it doesn´t change the fact that the user can get the passwords out of your program. => Just don´t. – deviantfan Jun 26 '15 at 13:49
  • 5
    ...todays security stuff was invented and checked over decades by lots of intelligent people. Don´t roll your own solutions, it won´t be better. – deviantfan Jun 26 '15 at 13:53
  • 3
    $ strings [your file]. Now I have all the strings in your file. Obfuscation doesn't prevent it, either. – Tyler Jun 27 '15 at 3:15
  • @Tyler I don´t understand what you want to say. Obfuscators can scramble strings and/or replace them with code to generate them from other data. How does your suggestion helps then? (many obfuscators won´t do this, but it´s possible) – deviantfan Jun 27 '15 at 3:16
11

Please, do not Hard Code credentials or hashes.

Hardcoded passwords may compromise system security in a way that cannot be easily remedied. [...] it also makes fixing the problem extremely difficult.

See OWASP page about Hard Coded Passwords

[...]many hashes are reversible (or at least vulnerable to brute force attacks) - and further, many authentication protocols simply request the hash itself[...]

See OWASP page about Hard Coded Crypto

Do not include any credentials in your source code, including (but not limited to) usernames, passwords, certificates, token IDs, or phone numbers.

And their guide to authentication

4

That is actually far less secure.

In an ideal world, where your database is not sitting in the DMZ but is instead only accessible directly from your web server, and then with limited account rights, in order to breach your database and retrieve your hashed password table, I have to:

  1. Expose your software database connection variables (account/password) by
    • Breaching your web server to gain shell access to it -or-
    • exploiting a weakness in your application to expose its DB connection variables directly
  2. Connect to your database. I may need to be able to do this from an SSH to your web server or through hosting compromised code on it, unless I manage to use some form of IP spoofing that is successful in bypassing whatever routing/firewalling you have your database behind (unlikely).
  3. Retrieve the table. This may not be possible on the account I compromised via step 1, if it is not actually comparing values itself but is instead passing a hash of the current login attempt to a stored proc in the DB on an account that is limited to accessing that stored procedure.

If I can't use your program's account to read the table directly, I'm basically done unless I can either compromise an admin account on the db server or otherwise compromise the db server's VM fully.

And this is all before we get into the question of whether your own hashing scheme is even secure.

In terms of the user names and hashes being "hidden," they're simply not, even if you use compiled code. Things like user names are going to be immediately evident in even a quick pass through with a hex editor.


Security works best with layers that both serve real purposes and decouple raw data into the smallest partitions needed to allow leveraging it as usable information, while only passing the requisite related information in its most minimal form and not the data itself whenever possible


Your approach puts all of the eggs in one basket

My necessary steps that go over the network are:

  1. Find a way to expose your code for downloading.

That's it. If I get your web server to cough wrong and your code-behind files are able to be pulled down directly, you're done. I don't even need a deeper compromise of the web server than anything that might result in that (which can vary based on whether you have them in an otherwise web readable directory or not). Alternatively, if I find a vulnerability in your code, I could potentially get it to just directly spew out the stored user names and hashes. And of course there's still that same possibility of simply fully compromising your web server.

There is no way to slow down an attack vector like this, presuming you detect a breach at a given level before it has reached other levels: a single breach immediately exposes everything. Even if we're talking compiled software, a skilled attacker will now know not only your hashing algorithm, but also your pepper if you are using one, along with effectively having access to your hashed and salted password table.

To put the second principle more simply, your software itself does not ever actually need to know a given user's stored password directly in order to authenticate them. It just needs to know if the password it has been given is the same as the one stored, which is something the database can determine for it for it, in a way that prevents the credentials your software is using from ever maliciously accessing the database (beyond trying to bruteforce from the stored procedure made available to the software, which presumably you would detect based on # of attempts and velocity and shut down).


Do not roll your own authentication unless there is no other alternative, or you're sure you actually know all of the rationale behind everything you're trying to do, and are willing to duplicate effort that has probably seen more and better review than you will ever get yours passed through. It isn't worth your time, and it will almost always result in something less secure than an established library or package.

If you think you are being clever by doing something different than industry standard practices, think very long and hard about whether or not there might actually be very good reasons behind those practices.

Once user credentials are in someone else's hands, even if you hashed them—even if you knew what you were doing and hashed them well, which is rarely the case when people try to roll their own security—you have to assume they are compromised. It's truly only a matter of time. Your best hashing efforts are only a delay at most in which you have a window to inform users and lock accounts until passwords are reset.

1

Another problem that I see here that's also related to security: suppose one of your users has to change their password because they were infected with a keylogger or a phishing attack. How will you manage to do that? The only way you can is by asking them for their password, rehashing that password, then replacing it in your code, recompiling and then republishing. That's a lot of "re-"s that YOU have to do. If you use a database, you only have to create 1 "change password" page and hook it into your database. Done.

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