views:

132

answers:

2

This probably sounds like a terrible idea at first glance, but here is my scenario: I have a Windows service that exposes several WCF endpoints using Username authentication. The custom authenticator will either look up the user's credentials in a local database (password is stored as salted SHA-1), or it will make a WCF request to another service to validate the password. (There is an enum on the User object that can be Internal or External, indicating which authentication source to use).

I'm finding that performing either the lookup+hash check or making the WCF call is expensive to do on every single request to my service, so I would like to cache username/password information. Each item in the cache would have a lifetime, so for instance if the item in the cache is 60 seconds old, upon the next request the authenticator will verify the credentials against the original source instead of the cache, and then update it.

For the local database, I could simply store the username/SHA1 pair in a Dictionary, and on each request from an "Internal" user I would just have to re-hash the supplied password and compare it. For an "External" user, I would only have the plaintext password submitted to the authenticator, so it would be up to me to hash it and store it as part of the cache. Although this certainly saves me the overhead of a database request or a remote service call, I still have to perform the hash operation each time.

The service in question will run on an internal server with good physical as well as network security. Is it an acceptable practice to store the plaintext password in the cache instead of storing a hashed version? In that case my risk seems to be an attacker dumping the memory of the process and getting the passwords. If I consider that risk acceptable, is there any other reason I should avoid having the plaintext passwords in memory?

If I opt to use plaintext passwords, I think that SecureString could limit my risk to an extent. Is it worth the trouble to use SecureString (implementing it seems very roundabout)? I am well aware of the risk of persistently storing passwords un-hashed, however I'm not sure what the consensus seems to be on volatile storage of plaintext passwords.

+1  A: 

SecureString uses encrypted memory, so this would likely improve performance over doing the hashing yourself each time. But you would have to profile it in your environment.

As to the risk of storing plain passwords in memory, that is not a question which can be answered in this context. I could just say, yes its OK. Because it is for my situation, for various reasons. But that wouldn't be the same as yours.

Here is what I suggest: Consider the ramifications of the passwords leaking -- basically how much would it be worth ($ or $$$?) to a hacker to possess a password? Most security problems these days come from a financial incentive. Relatively speaking, pure vandalism is outclassed by these guys.

Now compare that to the possibility that the security could be compromised in a totally different manner, i.e. SQL Injection or telephoning a user to "Verify their account". If the $ value of a couple of passwords is high and there is no other way to obtain them, then perhaps you should keep encrypting them (and now you have justified the cost of a more powerful server!). And make sure you then secure the crypto keys -- once a hacker has your server, those keys are likely as easy to access as program memory.

On the other hand, if the value is low and there are other possible exploits readily available (and there often are), you could make a reasonable argument that it isn't worth the hacker's time to compromise the server and dump the memory.

Good luck.

Jennifer Zouak
Very good points. After some discussion we realized that the WCF custom username authentication is handing around the passwords in plaintext anyway, so at any given point in time there are plaintext passwords in memory (between authentication and when those variables are GC'ed). So having a cache of them (especially one that expires) doesn't increase our risk a whole lot. Thanks for the good points, I brought them up in our discussion and it helped us come to the conclusion that this is acceptable in our environment.
Brad
+1  A: 

The service in question will run on an internal server with good physical as well as network security.

As long as that is true from now till eternity (or the next patch, which ever comes first) storing a cached password in ram as plain-text is fine. If you where storing the entire password DB in ram (say your persistent storage is too slow) I think storing them as secure strings would be better, but since you are only storing a few passwords for at most 1 minute, I see no problem.

Scott Chamberlain
Unless you told me it was worth 1 million dollars to get that password -- then I might be tempted :)
Jennifer Zouak