Storing Credentials for Secured Resources?
diverman asks: "It is very common for web applications (be them Java, Perl, PHP, .NET, or shell script) to need knowledge about credentials to access another resource. Perhaps it's a relational database login, an FTP account for transferring files, or maybe a authentication credentials to another web service. Whatever it is, most developers have likely had to write a program that needs to keep a password for later use. The big issue now is: where do you put them?"
"Having passwords sitting around in clear-text isn't the wisest of ideas, and is against most security 'best practice' guidelines. Some apps and servers have chosen to base64 encode it (I believe WebSphere does this), and that's about as safe as clear-text. What I've been trying to find is a mechanism that behaves like how Apache loads properly signed SSL certs, that require a password when starting up the web server. The password could be used to decrypt a key-store for various application/resource credentials, and then make them available. Exact implementation isn't the question, as much as ANYTHING that does this at all. Are there any Apache modules that can place authentication information in ENV variables for executed apps, after decrypting them on server startup? Are there ways to have Java containers do something similar? It seems like this is something that is a very common problem, but not a very common question, with an even less common solution."
For perl, you could use a module which contains a hash of hashes. This stores only cyphertext keyed to values ( username => 'qifhhfwqe', password => 'aiuherg' for instance ).
In the application, you read the hash from the module and decrypt it prior to authentication.
Sure, someone who has both the code for the application ( which must contain the decryption routine ) and the perl module can decrypt the credentials, but it does prevent someone from reading a text / base_64 file for your username / password combination.
I'm sure other languages could impliment similar functionality; perl's just what I've been coding in lately.
A Human Right
PasswordSafe pretty good, and has several linux ports
"Having passwords sitting around in clear-text isn't the wisest of ideas, and is against most security 'best practice' guidelines."
MOST?!?
Which security guidlines say it is ok and what companies are using them?
Passwords are for "Authentication". Your user has already been authenticated. You are now looking for "Identity Forwarding" or "Identity Session Management". Do not use passwords are your Identity Token. Look at technologies like Kerberos, which use your password for authentication, give you a identity token in the form of a TGT (Ticket Granting Ticket), and then allow you to request unique (and optionally forwardable) tokens for each service you are looking to access.
In the web world, CAS provides proxy tickets, which can even be forwarded (for example, to an FTP server) as a stand-in for passwords via PAM.
10b||~10b -- aah, what a question!
If you require access to a remote resource that wants some kind of credentials
presented, and you don't want to get a human involved, then you have little choice
other than to store something that someone could take a copy of and use to impersonate
your system.
Set file permissions properly. Make password-containing config files only readable by the processes that need to read them. chmod 0400. Keep each of your apps separated in this way so that a compromise of one doesn't affect the others. This is the best you can do. Password obfuscation can always be broken.
If your system can automatically authenticate against a remote secure resource, then someone who compromises your system can make it do it again. The only other thing you can do would be to require human intervention every time a password is required (or a collection of passwords).
Hashes can't be decrypted (at least, the ideal hash cannot). That's why they're so secure (ideally, again). When the user enters a password, that password is hashed and compared with the stored hash. Thus the real password is never required to be decrypted or exposed.
You either have to store passwords on the system in a way that programs can get to them, which no matter what you do, is insecure, or you have to have someone there whenever the system reboots. And if you've got a vhost server with hundreds or thousands of domains hosted...
There are two solutions I can think of off hand:
1. If the application allows, make the database or other sensitive resources append-only by the basic app. Further access requires the user to login with higher level credentials.
2. Have some sort of media with "read-once" properties; when the system is rebooted (which typically triggers a reset of some sort), the read-once is reset. The necessary connection parameters can be stored here then.
Plain text. On my desktop. Named "sensitive passwords.txt".
:)
I'll trade a paper version for a candy bar.
I am your users!
I do this on my servers without using passwords. What I have is a keypair (ssh) that has a very long (256+ chars) passphrase. Then I have a ssh-agent running on the box. Each bash script then sources a file I create in ~/.ssh/my-agent.env that sets $SSH_AGENT_PID and $SSH_AUTH_SOCK.
Whenever the agent doesn't have a key added, I can just do ssh-add, then enter my passphrase and it is stored in the agent. When I exit, that agent is left running and all scripts then source the env to get to the PID/Sock for my agent.
This works for shell scripts, but you could use it in other areas too with some code. So even if someone stole the keypair, the would have to brute force the passphrase to use it. And no passwords are kept in my scripts.
Only requirement is you add a key as soon as you reboot the box or your scripts don't work. A simple ssh-add -l will show keys and you can have the scripts exit/email error if no keys are added to the agent.
One approach is to compute a salted cryptographic hash of the user's password and store that instead of the password. A cryptographic hash is a fixed-length 'fingerprint' of some string and provides reasonable guarantees that, given a particular hash it is difficult to determine the string that created it (i.e. the original password) and that finding any string that results in the same hash is also difficult.
When the user submits their password (over an encrypted channel!), you compute the salted hash for the submitted password and test it against the one you have stored.
If your database of hashes is compromised, it is difficult for the attacker to find out the users' passwords, as you never stored them.
Now let's assume that an attacker gets your database of usernames and hashes. People are bad at choosing passwords, so it would not be suprising that two people woudl have chosen the same password. The attacker might take a dictionary of words and common passwords, compute a hash for each one (or just obtain pre-computed hashes for a dictionary) and then compare those hashes to each one in the user database. If they find a match, they have found the password. If two of the hashes in the user database match, the attacker has found two passwords.
If, before you compute the hash and store it in the database, you 'mix' (e.g. by pre-pending, appending or otherwise) a random string (called the salt, which is also stopred in the database) with the user's password, you can be reasonably confident that the attacher won't be able to easily tell that two users have the same password and will be forced to run their dictionary attack manually, by computing a hash for every combination of dictionary word and salt, for the commonly-used ways of salting passwords, which will make their life much much harder.
Whenever the agent doesn't have a key added, I can just do ssh-add, then enter my passphrase and it is stored in the agent. When I exit, that agent is left running and all scripts then source the env to get to the PID/Sock for my agent.
I do exactly this for my rsync backup. Arguably it's really the best/only way. But what would be better is a krb5-agent so that you can use the same technique with all kerberized applications and not just SSH. Of course this assumes you're just doing intrAnet stuff. For the intErnet, then I guess SSH is still the way to go.
Also, I have to wonder if ssh-agent is actually safe. It seems to me, it would be possible for a malicous program to deduce the PID/Sock by looking at /proc and trying different sockets in /tmp.
Why not just store the username/a hash of the password in a cookie?
3 /lib/CGI/Session.pm) might work.
The credential check would then be a comparison of the hash and a hashed entry in a database. This way, the password is never stored in plaintext.
Another method that I've seen involves a one time pad with sessions (stored on the server), so that no single side has sufficient information to determine the password. The only problem with this is that the password length would be revealed .
Of course, you could then just take advantage of sessions and store it on the server side. For Perl, CGI::Session (http://search.cpan.org/~markstos/CGI-Session-4.1
Ricky
Try Data::Encrypted found on CPAN (http://search.cpan.org/~amackey/Data-Encrypted-0. 07/Encrypted.pm)... From the module 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.
Put it into a tiny sample jar of pineapple jam which you give to your aunt Emma (aunt Emma doesn't like pineapple jam) for her to put in the barley hopper. So, this way, nobody will know the password and be able to know, unless they read /.
2. Have some sort of media with "read-once" properties; when the system is rebooted (which typically triggers a reset of some sort), the read-once is reset. The necessary connection parameters can be stored here then.
This is a good application for a TCPA TPM -- actually, a TPM can make this solution very strong. With a TPM, keys can be "bound" to a particular system state, as determined by the value in a register that stores a hash of all of the system state fed to it. If you encrypt the passwords (or other credentials) with a key that is bound to a particular (known good) system state, then when you get to that state during the startup process you can use that key to decrypt the credentials. Then, if you want, you can hash a bit more data into the TPM state, making that encryption key inaccessible.
An even better approach, of course, is to use cryptographic authentication to the remote services, bind the authentication keys to a known good system state, and then let the TPM do the calculations so the bound keys never leave the secure hardware. That way you don't even have to have authentication credentials floating around in RAM, and if you've done a good job of hashing the right data into the system state, an attacker can't insert a trojan which makes use of the keys, because the act of inserting the trojan will change the system state and make the keys inaccessible.
Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
Where I work, you must have a capital letter, and at least one number. You must change it every 4 weeks, and you cannot reuse any of the last 9. I consider this just on the verge of silly, but it can easily be circumvented like so:
Pick a person's name, say, Annakin.
Add a number or two to the name, Annakin123.
When the password expires, change to Annakin234, then Annakin345...
3) Profit!
Our AD guys are constantly battling the Infosec weenies who claim we need to have even stricter passwd policies, which will result in even MORE Post-It notes underneath keyboards.
If you share an account over which you have no control, get Passkeeper, or develop a "seed" algorithm, that knowing the code, and the seed word, and the hostname, you can derive the password, so you can easily remember it, i.e.
Seed is "slash"
Algorithm = seed + 3rd octet of hostname + first letter of hostname + last letter of hostname.
(or similar, I just thought this up off the top of my head)
Immune to all but dictionary attacks, and you and coworkers can easily derive it on the fly.
Potential security breach? Just change the seed word.
I want to delete my account but Slashdot doesn't allow it.
There are other ways than storing a password. For example in Windows ASP/ASP.NET you could use a domain account to run your app and then use windows integrated authentication on a SQL Server database.
I think you missed the point. This is not storing passwords for the purposes of authenticating users that enter their passwords. Yes, in that case, a hash function should be used (although, why anyone would reimplement such a thing that has been implemented a billions times over is beyond me).
The situation is not with authenticating user input credentials, but with an application needing to authenticate to remote services/resources (ie. the database connection, an FTP connection, etc). In this case the web application is the thing that is logging into another resource.
Our AD guys are constantly battling the Infosec weenies who claim we need to have even stricter passwd policies, which will result in even MORE Post-It notes underneath keyboards.
If your company has InfoSec guys, it can afford an audit to point out that they're idiots. If your InfoSec guys are confident they'll be happy for outside verification. As you say, Post-It notes. If security is really that important y'all need to be relying on multi-factor authentication, not some dork who wants attention.
My God, it's Full of Source!
OUTSIDE_IP=$(dig +short my.ip @outsideip.net)
http://wiki.jboss.org/wiki/Wiki.jsp?page=JaasSecur ityDomain
A coworker who has also been looking for options on this came across this page on JBoss's site. At first glance, it seems this is an attempt to deal with the issue first mentioned. I think it's JBoss specific though. And it's just an interface. And of course, RedHat bought them, so who knows what the future of JBoss will be.