Keeping Passwords Embedded In Code Secure?
JPyObjC Dude asks: "When designing any system that requires automated privileged access to databases or services, developers often rely on hard coding (embedding) passwords within the source code. This is obviously a bad practice as the password is then made available to anybody who has access to the source code (eg. software source control). Putting the passwords in configuration files is another practice, but it is still quite insecure as cracking hashed passwords from a text file is a trivial exercise. What do you do to manage your application passwords so that your system can run completely automated and yet make it difficult for hackers to get their hands on this precious information?"
Use SSL with certificates. It's more easily automated and just about anything worth running has the option.
Specialization is for insects. -Heinlein
Just `strings` and patience.
I wasn't aware that it was a common practice to store database passwords as hashed strings in configuration files. Does your program run a brute-force attack against the hash every time it needs to create a database connection?
On-disk passwords simply aren't secure. If you need automation, you want to secure the systems as much as possible.
That said, salted hashes are pretty tough to crack. Changing the passwords regularly will make it unrealistic for a cracker to obtain the passwords through brute force.
You can't secure a client-side password without another password to protect it. Which is contrary to what you're trying to accomplish. If you could give a bit more detail about what you're trying to accomplish, we could probably better enumerate the trade-offs.
IANRAProgrammer, but...
I believe public-key cryptography could do this. Encode the public key (several kilobits, if you're paranoid)? in the source, and have the program use it to authenticate the secret key given by the user. Publish the source code on YouTube for all the good it will do an adversary, right?
Paleotechnologist and connoisseur of pretty shiny things.
Putting the passwords in configuration files is another practice, but it is still quite insecure as cracking hashed passwords from a text file is a trivial exercise.
This simply isn't true. If salting is used (which is quite commonplace these days), it's pretty much going to be impossible to recover the password from the hash.
Cyde Weys Musings - Scrutinizing the inscrutable
Kerberos was built for just this situation. Read up on it. I think its even available as Active Directory for MS.
"We Don't Need No Truthless Heros!" - Project 86
'chown apache:apache database.conf && chmod 600 database.conf' That's good enough for me. Generally I'm not concerned with people accessing the physical hardware in order to bypass permissions, that's another issue entirely.
The better practice would be to make raw access a non-issue. Don't give the user account the privileges to accomplish anything that wouldn't be possible with the application itself. If you're using some sort of SQL database, consider limiting the permissions on the account to stored procedures that correspond your application's features.
First: only an idiot would put a password into source code. That's what configuration files are for. What, you want to have to edit a script every time the password changes? Second, there's no point encoding, encrypting or otherwise "securing" the configuration file. If a user has access to your configuration files, he has access to everything else, and all your security is useless. So really the question is: I don't want the neighbours to see me naked. What should I tattoo on my butt-cheeks to make me safe?
I have discovered a truly remarkable
If you want to do something quick and dirty without bothering to code in some robust password mechanism (let's say you want to use the same old password every time, hard coded as you say), why not creat a function to generate the static password using deterministic methods? People with access to the source code wil lbe able to spot what you've done, but at least they won't know the password without actually running the code. You could try to obfuscate the function as much as possible and store the generated password in dynamically allocated memory. This way someone who merely disassembles the code can't read the password plainly.
w/o trusting root, your whole application comes crashing down. All the chmodding in the world won't save you from root.
The only other way to do this would be to have your app retrieve the key from a trusted remote location via SSL, then use it on the remote app... which is sounding more and more like a kerberos or mutual SSL key thing anyways.
I want to delete my account but Slashdot doesn't allow it.
You (or your application) doesn't hash the password, the authenticating system (in this case the database) does. Possibly. Depends on the database. In any case, the app is acting as a user in this context, and so presumably needs the password in plaintext, as a user would.
The appropriate solution for something like this is defense in depth, so that a compromise of one element won't necessarily invalidate your entire protection scheme.
1. Lock down the database user. Grant only permissions that are required for the app to work correctly.
2. Lock down the database and app servers. Make sure your app is running under a restricted account, and that said account is the only one with access to your password file/application code.
3. Lock down the database connection port. Only allow connections from the app server's IP. Ideally, the database should be on a non-routable subnet with access only through port forwarding.
4. Lock down the data stream. If your database supports a PKI implemention, use it to authenticate and encrypt the connection.
First, let me dispose of one issue:
This is obviously a bad practice as the password is then made available to anybody who has access to the source code (eg. software source control).It's much, much worse than that, because the password is also available to anybody who has access to the binary. "man strings".
Others have suggested various options, but absolutely none of them work.
The bottom line is: If the machine has all of the information needed to perform the authentication without human intervention, then an attacker who gains control of that machine has all of the information needed to perform the authentication. Period. No getting around it. The best you can do is limit the damage in the case where the attacker has only partial access.
What is that best? For a network-accessible machine, do the following:
That's a lot of work, and it's still not completely secure. Luckily, very little needs even that level of security. Oh, and there aren't any OSes available that make good use of a TPM yet, so it's not really possible.
For most systems, what I'd really recommend is: Put the auth credentials in plaintext in a config file and limit access to that file to the bare minimum. If you have Mandatory Access Controls (e.g. SELinux), configure them to allow only the server process to read that file. Then, lock the whole system down as tightly as possible (within existing constraints). Ensure that a bare minimum number of people have logins on the machine, and that they all have minimum permissions, firewall it as completely as possible, and keep it up to date on security patches. Finally, put it in a locked room and tightly control physical access to it.
Of course, even this reduced-security approach is too onerous in many cases, so you have to make compromises. That's where a good understanding of security and plenty of hard thinking about what compromises can be made come in.
There ain't no silver bullet.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
It's all about managing your risk: This is what I do:
Is the system 100% secure? No. Is the system secure enough? Yes! The key is risk management; the probability of our system being comprimised is incredibly low. We're more likely to be comprimised by a disgruntled employee; besides, anyone trying to get sensitive data would have to spend an entire week figuring out the damn thing!
The key to senarios where a password needs to be stored in a machine-readable format is risk management; you reduce the risk of being hacked such that the overall value makes the system beneficial.
No, I will not work for your startup
... if the code with the password in it runs on your server, and never ever leaves it, and noone but you has any access to it. This is a completely valid way to deal with things, although it's ugly and if your server ever gets stolen, you'd better be using some kind of full-disk encryption. And if the server ever gets pwned, then your password will be pwned, too.
I see a lot of elaborate answers, but we all seem to be forgetting something obvious. When the service comes up, have it prompt an administrator for the password then store it in memory. Ultimately this is only obfuscation, but despite passwords getting stored in memory all the time and I think the rate of compromise remains fairly low. At any rate, it is a lot less likely an attacker will find it there than in a plaintext file on the disk. Apache HTTPD and all the MTA services I use do this when using SSL certificates with encrypted private keys. Seems like a good start, at least. If you want to get a little more elaborate, your service can generate a random key on some interval which may be used to encrypt that password in memory. Advantages of all this? No plaintext storage, it becomes easy to change the password of your database (simply inform the administrators), none of the developers need to be concerned with the credentials, and your code keeps the password (and the key for encrypting it in memory) a moving target.
Why bother.
Have it cached in memory only (no swapping), meaning you have to enter it each time a machine restarts..
I've done some preliminary testing and here's basically what it does:
My only concern is that Cloakware licenses CSPM per-application ID (the software is "free").
First thing, storing passwords is a bad idea but sometimes cannot be avoided. There are a few things that can be done. None can really prevent someone from dumping the memory contents because, unless you use more sophisticated client/server validation (based on IP, MAC, host auth, etc.), someone with the right privileges can core dump the system or strace the process. Yes, if someone has access to strace a process you probably have bigger issues, but it's conceivable in a DMZ environment where a particular host is compromised.
1) With most implementations of crypt() you can specify a salt value. This salt can be hardcoded or based on some property of a secondary file. For example, store the hash in a config file, but use the MD5SUM of another file as the salt. This prevents someone from just running the script/binary elsewhere and extracting your passwords.
2) Use a proxy mechanism that you can control. I.e., you may not be able to modify the server side, but you could setup a secondary server with restricted privileges that acts as a gateway to the database. Instead of the DB being accessible from a DMZ, the accessible machine authenticates against the proxy. You can set up many times of authentication on the proxy.
3) When possible, keep the stored password in memory only as long as is necessary to build the connection. I.e., clear the memory immediately after auth to prevent a dump from showing the plaintext of the password.
The only secure way on current hardware for automated authentication is not to embed passwords in source code. If you're willing to use extra hardware, your best bet is a smart card.
I remember seeing something to solve this elegantly on CPAN a while ago... The module is called Data::Encrypted and does almost exactly what you ask.
0 7/Encrypted.pm
.ssh subdirectory of their home directory (found using File::HomeDir), but you can provide alternative key files yourself, either by supplying alternative key filenames, or by building Crypt::RSA::Key's yourself:
http://search.cpan.org/~amackey/Data-Encrypted-0.
DESCRIPTION
===========
Often when dealing with external resources (database engines, ftp, telnet, websites, etc), your Perl script must supply a password, or other sensitive data, to the other system. This requires you to either continually prompt the user for the data, or to store the information (in plaintext) within your script. You'd rather not have to remember the connection details to all your different resources, so you'd like to store the data somewhere. And if you share your script with anyone (as any good open-source developer would), you'd rather not have your password or other sensitive information floating around.
Data::Encrypted attempts to fill this small void with a simple, yet functional solution to this common predicament. It works by prompting you (via Term::ReadPassword) once for each required value, but only does so the first time you run your script; thereafter, the data is stored encrypted in a secondary file. Subsequent executions of your script use the encrypted data directly, if possible; otherwise it again prompts for the data. Currently, Data::Encrypted achieves encryption via an RSA public-key cryptosystem implemented by Crypt::RSA, using (by default) your own SSH1 public and private keys.
RSA Authentication
==================
Data::Encrypted uses RSA authentication to encrypt and decrypt its data. It achieves this by reading the user's public and private RSA keys. By default, Data::Encrypted assumes these files are stored in the
As much as it pains me to admit this, Microsoft provides a nice solution to this problem.
For example, Keeping secrets in ASP.NET 2.0 or Wrap the Data Protection API
The trick is that they use the user's password to encrypt the data. Tight integration with the operating system has the occasional benefit.
So what do you do when you suspect a backdoor in the software published by a monopoly or by each member of an oligopoly? Do you put your business on hold for 20 years waiting for the patent to run out?
Sure it was, they could have contracted someone else who gave them the possibility to review the source code.Unless it is not commonplace for the monopoly or among the members of the oligopoly to allow third parties to review the source code.
http://freshmeat.net/projects/sentinel/
i did this for sentinel. i used an executable packer and a number of different means for keeping the salt secure, such as splitting it up and randomizing it during compile. you can look at the source as it compiles...its strings proof but not perfect.
To compliment comments made by the first response, there are only two situations where you need an administrator to supply the password. Once when the system is first brought online and then every time afterwards the system experiences a critical fault or scheduled maintenance that requires services to be restarted. In both cases, there has to be staff available. Especially if a system goes down (which it should not typically do) then there is likely a problem that demands attention. Otherwise, under nominal operating conditions, the service requiring the credentials would run without any additional attention.
Why bother.
Don't authenitcate the application to the database. Authenticate the user to the database. The user supplies a credential (password, certificate, biometric, etc), and the application, acting on the user's behalf, forwards the credential to the database. The database consumes the credential, performs authorization, and delivers data to the user, again through the application.
Kerberos provides a great mechanism for this. Using pkinit, you can use various credential types. Or, stick to the basics and use passwords. Most databases support GSSAPI (or SSPI) now, and using GSSAPI in your app shouldn't be too difficult.
So, the user supplies credentials on demand, nothing is embedded in source, binary, or external configs.
10b||~10b -- aah, what a question!
Alas there are no real good way to keep things secure in source code. But there are a few good ways to keep things afloat anyways:
Q. Your coders are not to be trusted
A. Put a file containing a security token (using the generic term token here, depending on what you use - certificate, or others). Open the file, read the token, send it to your server
A2. Use SSL tunneling, using aforementioned certificate, add another file for server details
A3. Create a "mirror database" with all important information replaced with random equivalents, send a new security token file for your coders using that mock-up database.
Q. Your clients are not to be trusted
A. Have fun with the password. A good Xor is usually enough for it not to be recognized by the user if he opens the executable.
A2. If your code can be hacked, you got more problems than that. Add up a anti-hacking protection to your software. Then make nontrivial encryption with your password, beware that your cleverness in your code might not show up as clever in assembly and might be very easy to understand inside the assembly code, especially with modern optimizing compilers and linkers.
A3. If you use 3rd party external tools to access your database (dynamically linked libraries, like DLL in Windoze), game over. Don't. This can be sniffed. If your database is in another computer and your SSL code is outside your code, don't. Again, game over. Everything must be embedded inside your own executable, and you must protect your executable.
As you can see, the "good" answer is nontrivial in both case, and it must be noted that no matter what you will do, someone with nothing else to do and big to gain (if only for the challenge) _WILL_ get access to your database. That's not the way to go if you want my opinion. Trust is the way to go, and if they can open up the database, well good for them. If you are DoD or some whiznut organization that needs to keep its eggs secure to no avail, if you don't trust your operatives, if you don't trust anyone, well, create a portal application that makes allowance and disallowance possible, then create a protocol to access that portal application that is heaviliy encrypted, then give out (at least) a 2-way encoding system using a hardware key (potentially obfuscated) and a nontrivial password, hashed with a inner application key that contains the version of the software, and the specific build in it, and create a encrypted tunnel using these values. Even then, someone with enough means will be able the get through.
Remember, once you get all the pieces of the puzzle, you get all the pieces of the puzzle. End of transmission.
To end up as a rant, RTFM, Applied Cryptography is there as your friend. Especially the first few chapters explaining what can be done and not done.
Encrypted file systems have a similar problem. They need to decrypt the filesystem for authorized boots or mounts, but need to stay encrypted otherwise. One common trick here is to only make the decryption key available once, at start up, after which it is put into memory, preferable with a small amount of obfuscation to slow down memory walkers. You could then use something like FUSE to mount the encrypted filesystem with your plaintext password.
As other folks have wisely pointed out though, the best posture is to use mandatory access control and restrict access to the configuration file. If you have the privileges, another good practices involves removing all compilers from the machine, firewalling all FTP traffic in or out, firewalling egress (outbound) HTTP traffic (pull in files to process), restrict SSH traffic to pre-defined nodes and enforcing that with a firewall ruleset. Preferably, you'd make all the firewall stuff occur on a separate box. What this does is restrict what tools will be available to an attacker. You can also remove fun programs like strings, ldd, od, *hexedit, and so on. "But I need to modify these tools!" you say. Leave SVN or CVS clients on the node, check your changes into SVN/CVS on your test bed machine, and then just check out the latest stable branch on your exposed machine. Then you get good protection and good configuration management all in one swoop.
Other tricks involve establishing a proxy process or strict limiting what can be done with the compromised username/password. A proxy process might be a setuid C program that only does one thing and accepts no user input. If you must accept user input, be extremely strict (use sscanf on all inputs and limit the size of the buffer accepted) and then have an experienced C developer review your code for improper bounds handling. This proxy process might do things like move files to a read-only directory structure (static web pages in a DMZ), or it might be a CGI script that updates rows in a database. We've actually used the CGI script idea because it a) it a cross-platform way of talking to the database, b) is a good decoupler of otherwise complex code, and c) strongly limits what can be done as an attack. Be careful of the venerable SQL injection attack there though.
A good use of a proxy process might be the transparent mounting/unmounting of an external USB drive, perhaps against a hidden partition on the stick. The drive would have your key. Sure it's obfuscation, but it's complicated enough to decode that it will slow somebody down for a while.
The last trick is to limit what can be accomplished with the username/password that is obtained. We have some processes whose job is to inject data into the database for the backend to all of our tools. That database user is limited to select, insert, and update operations. With Oracle, I could even restrict which specific tables get which privileges.
The best thing to do is to write a document that some folks call the Security Design Document to define your security posture, what you are known to protect against, and where you are vulnerable. Assign a risk mitigation matrix (vulnerability, threat, countermeasure, residual risk) row to each vulnerability. Be honest and then let your manager understand the position you've left them in and try to assign a cost to each countermeasure/mitigation so they can make a decision on what to close or leave open.
You are always going to have vulnerabilities. Everyone does, even the best systems. What makes the difference is those who analyze, understand, and counter that risk in a way that is appropriate to the situation. Direct exposure to the Internet is a situation that should warrant better risk analysis, but rarely does.
A long time ago, I started this mentod of doing this on suso.org. It caught on and now I encourage all my customers to do it:
d s.sdf
http://www.suso.org/docs/databases/mysqlinfo.sdf
http://www.suso.org/docs/databases/saferdbpasswor
I've thought about trying to spread the word about it and even making an RFC, but I don't have the time for that.
1. Do a cryptographic hash of the stored password for obfuscation
2. Secure the login connection
Is this over-simplifying?
The only thing new in this world is the history that you don't know.[Harry Truman]
You've got a machine A on the interior LAN, that needs credentials to access a DB on machine B on the interior LAN. You've got two choices:
...), but this quickly reaches a point of diminishing returns and can become a maintenance nightmare. You can obfuscate the key or even build it on the fly to make it more difficult to extract it from the application (for binary apps - it helps to strip the symbol table). Use the OS permissions to restrict access to the config / key file and the (web) application. This won't stop a determined intruder, but they'll have to work for access, and it will slow them down.
1) You can store the credentials somewhere on machine A.
2) The service (typically a Web server) on machine A can run with an account that's either has privileges to access the DB or has privileges to access credentials stored somewhere else to access the DB.
If an intruder gets access to machine A and gets root / admin privileges - then they can gain access to the DB. Obviously, you're first priority is to make sure that this does not happen! Use good firewalls and firewall rules. Make proper use of a DMZ. Check your application for security problems (buffer overflow, SQL injection, etc). Keep up to date on patches. Your second line of defense, is to:
1) Try to insure that an intruder is detected.
2) Make them work for it (access to DB)
3) Have a good audit trail
4) Monitor your network and application
I'll address item #2. Assume that you put the credentials in the configuration file or a separate file on machine A. You should encrypt the credentials (using an encryption application NOT kept on machine A). The key can be hard-coded in the (web) application. If you want, you can use layers of keys(Encrypted key b decodes key in config file. Encrypted key c decodes key b, Encrypted key d
[Insert pithy quote here]
Ok, so you use SSL with client certificates for authenticating against the server, but you are worried that the evil doers might simply read the keys right off the disk.
In that case you can do what Apache and openssh does to protect that kind of information:
Encrypt the keys and store them on disk.
When the program starts (maybe it's just a keyholder process) then the user is prompted for a passphrase and the key is stored in memory, if the keyholder sees any processes it doesn't like on the machine (like a debugger) then it simply shuts down.
This means that the keyholder will need to be started by the user every time the system has been booted, but after that everything can be automated.
This would at least mean that the attacker will need to gain access to the machine with all the software running in tact to get to the key, so if he is forced to reboot the machine then you have won.
-- To dream a dream is grand, but to live it is divine. -- Leto ][
okay 1, don't let just anyone read your source code! It's not that hard! And 2, use ascii value tests cuz they don't stand out as much. This also protects DLLs from ASCII ripping programs. Like instead of testing a stored password of fish, you'd test for the ascii values....iunno, I'm too lazy to look em up but like 131,97,28,43 or whatever the letters translate to. If you split the test up into multiple subs that helps even more, ESPECIALLY if you put in fake comments and a fake name on the sub like "load program" when it really tests the password with comments that say it tests for keystrokes while the program loads. That would throw someone way, way, way off.
Google's Super Secret Search Algorithm: SELECT @search_results FROM internet WHERE @search_results = 'good'
Are you asking about a "default" password that you want to have available immediately at installation? Generate it on the fly during the installation.
/dev/urandom | tr '\0-\377' 'a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9a-zA-Z0-9@@@@####'`
This works well (all one line, of course):
PASSWORD=`head -c 8
Stick in a configuration file with restricted permissions and mail the location of the file to root so that the admin can change it.
Warning: this article may contain humor, sarcasm, parody, and perhaps even irony. Read at your own risk.
An entire operating system, from the ground up?
and live in a place where software patents are not valid to begin withWhich such developed country has a permissive immigration policy?
EU lawHave EU courts routinely dismissed patent infringement cases on grounds that on methods of communication involving arguably novel processes of data processing are not valid subject matter for a patent?
If the password is encoded within Java code, just use JAD for decompiling Java byte code into source code and then look for the password. There is even an Eclipse plugin called JadClipse, which make's password fishing even more fun. :)
Michael
Nerdy by Nature!
I'm working on software with a similar problem--I want to store the SQL database username and password in some halfway-to-secure fashion, because leaving it in cleartext in the PHP is just asking for the database to be compromised. So, the only alternatives are to encrypt it within the code or to put it in an external file. The external file makes it easier to change the username and password after the fact, so that's where I'm going.
Problem here is that the contents of the file need to be encrypted in some way. Using a key-based encryption still means that a password needs to be stored in cleartext somewhere, so it needs to be non-key based. Downside to this means that anyone with access to the source can decrypt it trivially. Best you can hope for, rather than making it completely secure, is to make it difficult to determine the cleartext from the cyphertext. So, you have to encrypt it a couple of times using different algorithms and get the cleartext the hell out of memory as soon as possible. From what I've been reading in this thread here, it's really the best you can hope for.
/me deposits two cents in the jar
Matthew G P Coe
http://mgpcoe.blogspot.com/