Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I have an internal business application, that as part of its functionality connects to a third-party app using login credentials specific to the user of my own app. These passwords are stored in a central database. Currently they are plain text (this was justified based on a high level of front-line security into our corporate LAN), but a recent attack against the network of our new parent company (luckily they didn't actually get in) has led me to take another hard look at that.

Passwords for the main internal app, we can bcrypt them with a salt, no problems there. The problem is ciphering the third-party application credentials. As we all know, users like to keep the same password for multiple apps, so no matter what I do to the internal app password for safekeeping, it won't make a lick of difference if the third-party credentials are sitting there in plaintext right next to it.

Here's the kicker; whatever method is used, it must be reversible within the application, because the #$%^&* third-party app requires transmission of plaintext credentials from the internal app's process to a SOAP service (luckily it does so over HTTPS), and the internal application allows users to maintain these stored third-party credentials (saving the Dev department the trouble of maintaining DB content). So, the best I can do is encryption, not hashing.

So, I realize that any method I employ here will be less than ideal; if the attacker gets both the application and the credentials, he'll get the plaintext passwords and there isn't much I can think of to prevent it. I'm just trying to make an attacker work just that little bit harder to get the credentials, hopefully giving me enough time to at least alert the third party so they can disable our logins, if not force every user in the system to change their third-party credentials before the attacker can crack one.

So, what do you suggest? AES (I can't imagine RSA being of much use as the application has to both encrypt and decrypt)? Any clever tricks for keeping the key out of the hands of someone who manages to get both the DB and the application binaries?

share|improve this question
add comment

1 Answer

up vote 6 down vote accepted

Let's suppose that in your app (let's call it App1), the user already has to enter some credentials C1 (name and password) which App1 uses when it connects to your central database. Right now, your central database contains C2 as cleartext, to be used when App1 connects to App2.

Let H() be a hash function with a large output, say SHA-512. When the user enters his password (C1) in the interface of App1, App1 computes H(C1) and obtains a 512-bit value, which it then splits into two 256-bit halves, Pl and Pr.

The credentials C2 are symmetrically encrypted with a key derived from Pl. This derivation should be slow (like bcrypt or PBKDF2 or something equivalent); I suggest relying on an existing, well-audited format for the encryption details and the key derivation, e.g. OpenPGP. Let's call E(C2) the encryption result.

Now let your central database store E(C2) and bcrypt(Pr).

When the user enters C1 in App1, App1 applies H() to obtain Pl and Pr. App1 then contacts the central database and sends Pr (within a SSL tunnel, of course). The central database applies bcrypt() on Pr to see if that matches the stored value; if yes, it sends E(C2) back to the client. Then, App1 uses Pl to decrypt the blob and obtain C2.

This way, the central database never obtains the decrypted C2 at all; and C2 are known to App1 only in a transient way (in RAM, not "hidden" in the code). What the central database knows is sufficient to test a password for validity, but slow hashing and salting is employed to counteract that issue (as part of E() for Pl, using bcrypt() for Pr).

share|improve this answer
1  
+1 But doesn't this imply that if a user loses his credentials to the app, all of the saved passwords for his account are now useless? –  quantumSoup Oct 17 '12 at 20:08
2  
@quantumSoup: well, yes it does. This is the generic problem of password-based encryption: lose the password, lose the data. But if the data can be recovered without the user's password, then, well, it can be recovered without the user's password, which is the problem I wanted to fix. –  Thomas Pornin Oct 17 '12 at 20:12
    
The one issue I have with this is that it removes the possibility of admin intervention, except for creating or recreating accounts. Nobody besides the user can make surgical changes to a user profile; all an admin can do is blow the old one away and create a new one. That's all well and good if the user forgets their password, but if a user gets married and we change their user account in the third party system, either the user themselves has to make that update or we have to blow the user's profile away and rebuild it. –  KeithS Oct 17 '12 at 20:46
    
Despite that, you definitely addressed the basic need I stated in the OP, quite elegantly, so you get a +1 and the tick. –  KeithS Oct 17 '12 at 20:50
    
Does this answer your question satisfactorily, or are you also interested in an answer which allows passwords to be recovered? It's not as secure as Thomas' scheme, but there are ways to have this as well, but limit offline attacks. –  Stephen Touset Oct 17 '12 at 22:41
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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