April 9, 2019

Calling security experts: how to store sensitive data

nadima @ih11

Companies like plaid.com are storing your banking login credentials so they can log in on your behalf.
What is the indie hacker MVP for storing banking credentials?
I understand the concept of "defense in depth", but what is an acceptable first iteration for storing such sensitive data?

  1. 6

    These would need to be Salted and Encrypted in the same way for any company that is storing Sensitive Data such as banking details (As strong encryption as possible and a unique salt). This way if a breach does occur it is as close to impossible as can be to get this data back to the original state.
    Just because it is an MVP does not mean it needs to lack security as this can be the backbone going forward as well as what is needed to build the trust that can make/break a product.

    1. 1

      Just to be clear, the data needs to be decrypted back so symmetric encryption is needed; in case of breach if the hacker has the decryption key they will be able to decrypt the information.

      1. 2

        Take a look at https://privacy.com/security - some ideas there, including partial keys controlled by different employees etc

        1. 1

          Interesting this split key concept, will come in useful once i have a team.

      2. 2

        Yup, don't store the decryption key and the encrypted data itself in the same database

  2. 3

    I run a security company called Sharesecret. My advice to you is — don’t. Don’t store sensitive creds like banking info. It’s incredibly risky, especially for a bootstrapped product, you’re very likely to make a mistake, and more importantly you’ll burn an enormous amount of time building out that part of the infrastructure, and your customers won’t care. I call these parts of a product commodity infrastructure. People just expect it to work but you’ll never win a customer based on it.

    My recommendation is to use a hosted vault like Verygoodsecurity.com.

    1. 1

      Thanks for chiming in, I'll have a look at that website, these are the kinds of things I'm looking for.
      Is that product different from a solution like Google Cloud KMS?
      For example with KMS (and I believe with any 3rd party solution), I will have to store the Google access token somewhere on my application server, so anyone who can hack into my application server will be able to call the Google KMS endpoint and fetch the decrypted data. The encryption keys are stored with Google and rotated automatically by their service, so I can't do much to increase their security there.
      My issue is how to reinforce the weakest link which is always on whichever machine is used to store the 3rd party access token.

      1. 1

        It's very different from Google Cloud / AWS KMS. Those services are basically just hosted vaults, so your data security is dependent on your key security.

        VGS works quite a bit differently. Basically, it's a middleware layer for your sensitive data. You put it into a vault via client libraries or via HTTP proxy, and they give you back tokens, just like Stripe.

        To get it out, you proxy your outbound requests through them, and they substitute the tokenized values with the raw data on the way out. I'm not sure exactly how you would present sensitive data in your UI while keeping the raw data from hitting your servers, but you should chat with VGS about that.

        1. 1

          Ok so I created an account and went through their short demo.
          It looks like the added security compared to KMS is that when the user submits the request on my front end, the data goes to VGS servers first, who tokenize it and posts the token to my server where I will store it – as you say, much like Stripe.

          So the difference is that the plaintext credentials never hit my server when the user submits them. However, they will be in plaintext in-memory on my server when I'm running a background job that requires them (e.g. fetching the user's bank statement on a daily basis).

          1. 1

            Yes. Their system is quite unique in that, depending on your use-case, you can make use of your tokenized data and avoid the plaintext data from ever hitting your servers. For example, if you need bank creds to log into a customer's bank account, ideally you could post that directly to the bank website or API, and if so, you could proxy the request through VGS and have them substitute the plaintext values for the tokens when they intercept the request. However, that probably depends on the API's available to you from the bank.

  3. 1

    Just a heads up to consider multifactor authentication (MFA), which I recommend everyone use. If a user has this enabled, you still can’t access their bank account even with their username and password.

    1. 1

      How do services like Plaid and Yodlee get around this?

      1. 1

        I'm not sure, I believe through api access. Ideally, the bank would provide an api and you would get an api key and a token for each user, instead of username/password. From this documentation on Plaid, it looks like if MFA is enabled, the bank requires Plaid to get the MFA code from the user and send it back one time. The user would receive the authentication code, input it in your application, your app would pass it back to the bank api, and then you would receive a token to use in subsequent api calls. Authorized api access is really the ideal long term way to go. (https://support.plaid.com/hc/en-us/articles/360010402914-Troubleshooting-MFA-issues-in-Plaid-Link)

        1. 1

          Good find.
          It's likely that the vast majority of banks have no APIs and Plaid has no deals with banks that have MFA. As long as plaid or the app implementing it can prompt the user to enter an MFA code then problem solved.

          I know that for some banks, if you are logging in from a new device / IP they will send you an SMS code, then all subsequent logins from that device / IP won't require MFA. So once a Plaid server is approved in this way it will no longer need user intervention to do background jobs (e.g. fetch bank statement).

  4. 1

    One of my former roommates later became chair of an IEEE encryption committee. He would say, "either hire a security expert or outsource this to a company that has."

  5. 1

    There's a company that's called Very Good Security (VGS) https://www.verygoodsecurity.com/ - They're essentially an API for data security. Anything that you'd need to store securely can be stored in their vault, and you'd receive a token back to retrieve that data at a later point. Seems like a good potential solution for the problem you're dealing with.

    1. 1

      Thanks, indeed it was also recommended by @ajsharp
      I'm looking into it to determine how it's different than Google KMS; have you personally used it?

  6. 1

    Security is about risk mitigation, not risk avoidance. With enough money and motive, anything can be breached. So you have to ask yourself, what are you protecting against?

    Any sensitive information you have should be properly safeguarded. But against what threats? Only you can know that, and that starts by conducting a threat model on your system. I am a big fan of the STRIDE by element approach (https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling), but use whatever method you are comfortable with that will help you identify how data flows through your system, what processes access it, and where you can establish trust boundaries.

    However, I expect you are looking for more tactical advice. So I will make some assumptions on your behalf, and you can correct it based on your actual environment and conditions.

    First, you are going to need to ask yourself if you actually even need the credentials. Is there a way that you can gain access to whatever data/info you need without it? Do they support modern APIs that may use something like an OAuth 2.0 consent grants workflow where you can use limited access tokens instead?

    Let's assume for a moment you can't. You have to have their banking password. OK. Then you are going to need to ensure you collect it safely. So make sure that the page where you prompt for this only can run over SSL. Also ensure its the RIGHT SSL certificate you expect (to prevent SSL stripping and pinning to circumvent MITM attacks).

    OK, so now you have the creds collected and in your backend. Now you need to store them. Firstly, read the OWASP Password Storage Cheat Sheet (https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Password_Storage_Cheat_Sheet.md).

    Go ahead. I'll wait.

    Good read right? Ya, except it won't really help you here. If you have to store a password the recommendation is to instead generate a salted hash and compare that during authentication. However, you can't do that. You need the original password so you can use it to access the banking APIs/pages. So now what?

    As mentioned elsewhere in this thread, it comes down to proper encryption. And the problem with encryption is its only as good as the algorithm and key. Well, more the key. If that is easily obtainable, the game is over. So let's start there.

    Find a way to store and use the key separate from your app. Use a hardware security module (HSM) backed key vault, like Azure KeyVault or AWS Key Management Service (KMS). Then use application/service principals with least privilege read access to the key that can use it to decrypt the password at time of use. If this is all too confusing, just read the vendor docs on using these secret stores. They have some brain-dead easy examples to help you along.

    ie: If you have a backend process that needs to access the bank APIs/site put this execution on a separate worker thread that runs in the context of the application principal so it can access the key and decrypt the data. Lock that down so no external access is allowed, and process the data and then destroy everything in memory. As an example, I use a consumption-plan based Azure Function that accesses Azure KeyVault in the context of that FaaS to use a sensitive credential to collect the data I need which is pushed into storage, and then the function app destroyed. Then a separate function picks up the data and processes it, and has never seen the password nor had access to the cipher key.

    YMMV of course. But security engineering doesn't have to be complex or expensive. You just need to understand how to approach it. Always protect your customer's information and data. MVP doesn't mean insecure.

    Good luck!

    1. 1

      Amazing, that's a lot of new information for me to go through. So I already built a first iteration using Google KMS, but the part where you mention separating different processes and ensuring memory is destroyed when data is no longer needed will take me to another level. Thanks a bunch!

  7. 1

    If you accept credit card payments, you must comply with PCI standards, which are pretty tough (https://www.pcisecuritystandards.org/). I can imagine banking credential storage might call for something similar - do your research!

    Like others said, just because it's an MVP, you CANNOT cut corners on security. In this case, security must be one of the main features of the product.

    1. 1

      I don't deal with credit cards.
      I'll check out that link but is it realistic to achieve PCI compliance as a solo hacker?
      My understanding is that you can keep building security layers forever, so I guess my question is what would a solid start that gets me 90% of the way look like

      1. 1

        I think the point is that if whatever you are doing falls under some standard that you need to follow to avoid liability and lower your legal exposure later, then your "solid start" is pretty much defined by that standard.

        For instance, if you decide to use ACH payments, you must first figure out their Network Rules: https://www.nachaoperatingrulesonline.org

        Please don't take this lightly. The legal exposure of bad security and mishandled banking information to your personally and to your business might be very large - the liability might be larger than what it makes sense for you to take on. Go into this knowing your risks.

        One more thing: read privacy.com's terms and conditions to understand how they protect themselves. I use privacy.com and I love their product, and I'm sure they do a good job protecting my bank info, but even then, I've setup a separate bank account JUST in case they screw up and my data leaks - at least the damage would be limited.

        Think of banking credential information as nuclear fuel - if it leaks, everyone around is f-ed, starting with your business. If it's a risk you are willing to accept, then go for it, but at least you'd be doing it with your eyes open.

        1. 1

          Privacy's T&Cs seem to be saying "we are just not responsible for anything".

          from their site:

  8. 1

    I am not entirely sure if it fits in your product flow, but you could optionally use the users password for your service (so not the banking credentials) as the symmetric encryption key. You don't store it, but only have it when the user is singing in. You could then store the decryptor key (or even an encrypted version of it) at the client side or only use it in runtime/session memory.

    This is very much like how password managers work!

    1. 2

      very interesting concept, thanks!
      I actually need to be able to run background tasks that require access to the credentials without the intervention of the user, but your idea may have just opened the door to a different possibly more secure workflow. Thanks!

  9. 0

    This comment was deleted 5 months ago.

  10. 1

    This comment was deleted 10 months ago.