22

What's wrong with you, you crazy fool, you're not supposed to be able to retrieve a password in plain text!

I know. Hear me out.

Assume I've got a service that's similar to Mint.com. For those that aren't familiar with Mint, it works like this:

  1. User signs up to Mint.com much like they would any other online service - by providing an email address & password.
  2. Here's where things get interesting. The user then selects their bank name from a dropdown, and provides their online banking username and password to Mint.
  3. This is where things get really interesting. Mint stores these credentials and uses them to retrieve the list of credit/debit card transactions made by the user automatically - at different times of the day. They do this by automatically logging into the online banking site - using the users credentials (presumably through a browser emulator of sorts).

Now I need a secure way of protecting the online banking credentials of my customers.

Here's the big question: How would YOU do it?


Yes, I've already read this question and this one. The answers all suggest using a more secure method of communication with the 3rd party (either authenticating using API keys, or passing hashed parameters). In my opinion, and it's just that - an opinion - it seems to me like a genuine use-case where I have incredibly sensitive information that NEEDS to be available in plain text - at least periodically throughout the day.

Interesting fact: Mint.com has over 10 million users

5
  • 9
    If you're already going to break the rules once, by requesting that people hand third-party passwords over to you, how you break the rules becomes rather less relevant. Justifying it as "customer convenience" is no answer. In other words, don't store third-party credentials. Mar 9, 2014 at 22:55
  • I'd never trust my bank authentication credentials to a 3rd party.
    – Matrix
    Mar 10, 2014 at 7:05
  • @Matrix You won't. But over 10 million do Mar 10, 2014 at 8:30
  • Interesting! I wonder what will happen to Mint.com's business when 2-factor authentication / OneTimePassword (OTP) becomes a norm.
    – Litmus
    Mar 14, 2014 at 6:48
  • @Litmus: Good question! Hopefully, by then banks would have their own APIs to allow access to transaction data. Who am I kidding, that'll never happen! Mar 17, 2014 at 12:31

3 Answers 3

29

In the case you've described you're storing information on behalf of the user, and you're not using it to authenticate the user. Hence, while the contents of what you're storing includes passwords (almost exclusively), you're not really "storing passwords" in the traditional sense. You're storing secrets.

Adjust your strategy accordingly.

Both of these problems are solved; you just need to apply the correct solution. When "storing passwords" (that is, authenticating the user), you go through the hashing, the the salt, the key stretching, etc., that you're familiar with. But what about storing secrets.

First and foremost, you avoid the problem if possible. This is why concepts like API access tokens exist. You don't need my Facebook password because you can't use it. You need an access token which Facebook is willing to give you with my permission.

The next best solution is to tie access to user login. The information is encrypted using a key derived from the password you use to log in - which I don't know and don't store. So I (the server owner) can't access your data unless you type in your password.

This is popular because it's powerful. In fact, Windows has been doing this for a long time, which is why changing your password can cause encrypted files to become inaccessible. It's also the reason why your Windows password is stored in plain text in memory while you're logged in. An implementation snafu which I would advise you to avoid.

Next on our list, you can separate your processes such that unencrypted data is never available on outward-facing machines. Bonus points if an HSM is involved. The gist here is that the user provides his secrets to the web server, which are quickly encrypted using the public key to some secret crypto device which is totally inaccessible because it's not connected. The plain secrets get immediately forgotten, and the encrypted data then gets shipped off to some cold storage somewhere.

Eventually the secrets get decrypted somewhere else with the assistance of that crypto thingy and get used. Only, the point where this happens has NO INTERNET ACCESS. Or at least no path from the outside in.

Finally, you can try the solution above, but fail miserably. I only mention this because really all other solutions are just crappy variations on the ones above: encrypting in the database, using an application password, storing the password on another server, storing the data on another server, salting your encryption key with [silly idea here], and so on.

And finally, my standard warning for questions like this applies. I'll write it really big:

The fact that you're asking this question means that you shouldn't do it

Seriously. Storing peoples banking credentials? If you don't understand what sort of trouble you're getting yourself in to, if you're asking the Internet for suggestions on how to do this, if all the solutions I mentioned weren't ALREADY top-of-mind to you as the only viable options, then you shouldn't be implementing this.

People are trusting you to do this right. And you're not going to do this right. Not because you didn't ask the right questions, but because you haven't solved this problem often enough to understand what hidden pitfalls you'll have overlooked. This is difficult stuff: not difficult to do, but difficult to not make mistakes.

Don't betray the trust of your customers by getting yourself in over your head.

1
  • 6
    "The fact that you're asking this question means that you shouldn't do it" - you're absolutely right. I wouldn't plan on implementing this myself - I was going to get a security consultant to help out but wanted to get some background on what possible solutions may look like. Thank you for the elaborate, and incredibly informative response Tyler! Mar 10, 2014 at 8:26
4

While I disagree with this practice, if I had to keep very sensitive info in my server here's what I'd do:

  • Create a small daemon in the same server, and request that a human operator inputs a password/key on start.
    • Derive a symmetric encryption key and an asymmetric key pair from it.
  • Keep these keys on RAM only, prevent swapping.
  • When an user wants to send the sensitive info to the server, have them encrypt it on the browser itself using the public key (so only the daemon can read it). Have the daemon encrypt it using the symmetrical key and return to the main webserver - who can now store it.
  • When the system wants to do something with the sensitive info, pass the encrypted data to the daemon. It should then decrypt and ideally use it right away (for instance, make the third-party request - and don't log anything anywhere), erasing the plaintext and only returning the response (i.e. the main webserver does not "see" the plaintext at any moment).

You should of course use any complementary security practices you can, but the core of this technique is that only attackers with access to the live machine - capable of reading the RAM contents of another process - can retrieve the sensitive data in plaintext. Or if the attackers can inject their own code in the server, so at the next restart the operator inputs the password to their daemon. If they can merely send arbitrary commands to the daemon they'll be able to do as much as the daemon can do (i.e. read data obtained from those credentials, but not the credentials themselves, neither perform actions the daemon was not programmed to perform).

That said, if 10 million fools not too security-minded people did business with me, I'd probably afford to hire the best security professionals out there, instead of relying on my own knowledge only (as I do now). That might prevent my system from being the weakest link - despite how attractive it may become for attackers. Just keep this in mind before doing ambitious stuff that, while potentially useful, might get you in trouble if when things go wrong.

2

I wouldn't, unless completely confident that nobody would be able to crack into my database, I'd rather have that information stored on user's devices so my service wouldn't be responsible for any data leak. But if I had to do it...

When a user creates an account I'd generate a AES-256 key (lets call it a storage_key), then encrypt that key with a key derived from the user's password (lets call it a user_key) using some solid KDF (scrypt, bcrypt, PBKDF2...) and store it as encrypted_storage_key along with the salt, iterations and other parameters used by the KDF to derive the user_key under the user's account.

Then the process for entering/reading the data would look like:

  1. User enters a password.
  2. Using the selected KDF and stored parameters derive the user_key.
  3. Decrypt the stored encrypted_storage_key with the user_key and get the original storage_key.
  4. Use this storage_key to encrypt/decrypt the sensitive data.
  5. Don't keep the storage_key around in memory for longer than you might need it and never, ever store it in that form.

Of course, for this scheme to hold any security it is of paramount importance to secure the 'line' through which the user enters his/her password (e.g. SSL/TLS at the very minimum if we're talking about a website) - if somebody is able to get the original password the whole scheme falls to pieces.

2
  • Does this mean that i'd only be able to decrypt online banking password when the user enters their plain-text website (i.e. Mint.com) password? Mar 9, 2014 at 21:42
  • 2
    Yes, the above scheme would require the user's password in order to decrypt/encrypt the sensitive data, which means the user has to login to your service before such data can be accessed - and optionally, if you don't keep the exposed storage_key as a session entry, the user would have to enter his password each time you want to access the said data. This, of course, means that the data can be accessed only on user's request and is insecure only during that time. Mar 10, 2014 at 9:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .