Ask HN: How would you design password storage for a service like Mint.com?

11 points by pilom ↗ HN
I'm trying to figure out what best practices would be for a service like Mint.com.

Requirements: Allow users to store cleartext passwords to bank accounts which can be accessed by the service once per day regardless of if the user is logged in.

Usually, you only want to store hashes of passwords on your site but Mint can't do that, they need the cleartext passwords in order to log into banks. What is the safest way to store that customer data?

9 comments

[ 3.7 ms ] story [ 33.0 ms ] thread
If I had to roll my own crypto, and god help me if I had too. puts on tin foil hat

I'd store the clear text passwords encrypted with AES-256 CBC mode (still works right?). Next their would 3 databases, on 3 separate servers (hopefully physical ones). Server 1 passwords + salt, server 2 key 1, server 3 key 2. bcrypt(Diffe-hellman(key1,key2), salt) = AES standard key.

Basically I wouldn't. I couldn't sleep good at night storing financial data.

Would you have a 4th database of your own site's usernames and scrypt(local password) used for logging in?
Yes but I figured that went without saying.
This is tangential to the topic, but many banks do not care how secure Mint.com might be, and simply by using them (e.g. providing your password to a 3rd party service), you violate the bank's TOS [0]. This is the main reason why I will not use a service like Mint.com. If my bank account is compromised, for any reason (perhaps completely unrelated to Mint), I don't want the bank absolve itself of liability because I violated the TOS.

[0] http://www.moneysense.ca/spend/the-banks-take-a-bite-out-of-...

Use a tokenization service like PaymentVault to tokenize vs. storing.

http://www.auricsystems.com/products/paymentvault-tokenizati...

This is an interesting idea. Can you provide any guidance on How would I go about rolling out my own tokenization system? I don't have need of storing credit card info but would like to roll out similar system for other user info.
Your best and safest bet is not to need this feature in the first place.

Failing that, what you're probably looking for is something along the lines of a simulated HSM (let's call this an SHSM).

Decompose the system into four distinct services:

- The front-end application, "Mint" as experienced by normal users.

- A minimalized subset of "Mint", with Mint's chrome and UX, dedicated to the acceptance of credentials or secrets from users. Ideally, this is running on a separate instance.

- An SHSM system that exposes nothing but a simple remote API for sealing and unsealing secrets. Seal: secret->token; unseal: token->secret. The SHSM is on separate hardware, unshared by any other service.

- A backend system, hardened and carefully assessed (but not as hardened as the SHSM) that performs the operations that require the secrets and stores its results where the front-end can get access to them.

This design needs to recognize that:

* The minimalized secret-accepting front-end can be compromised and, if that happens, an attacker can "camp" n the front-end and collect secrets regardless of what else you do. That's why you segment this functionality from the main front-end.

* A serious flaw in the rest of the front-end might transitively give an attacker a pivot to owning up the secret-accepting front-end; this could be direct (for instance, if both share a database) or indirect (if the minimalized front-end renders attacker-controlled content accepted in the front-end).

* There needs to be a diode-like relationship between the secret-acceptor and the SHSM; the SHSM must allow the secret-acceptor to seal a secret in such a way that it can't later unseal it, else it's serving no real purpose (an attacker that compromised the secret-acceptor would be able to unseal all secrets).

* The SHSM itself must be locked down to exactly the minimum set of services required to perform the seal/unseal operation.

* Ideally, the security of the SHSM asymptotically approaches that of a real HSM; for instance, a hardware-augmented root-of-trust might be used to make it difficult for an attacker that (improbably) gains code-execution capability to instantiate their own SHSM process to decrypt secrets.

* The backend service, which might have unlimited access to the secrets stored in the SHSM, is itself a prime target of attack through clientside vulnerabilities (this is why you want to segment it off from the SHSM). Some combination of rate-limiting, anomaly detection, privilege, and user-permissions (a system might be designed to prevent the unsealing of a secret without some action having happened in the front-end within a window of time).

None of these problems are easy. You might plan on spending somewhere between 4x-10x the amount of time designing, building, verifying, and monitoring this system than you would a system doing something similarly complex with non-secret data.

It seems to me the best plan to "not need this feature in the first place" is going to involve reaching out to the organizations in question explaining your plans and asking for a way to set up revokable and narrow access. Not saying you're sure to have much success (probably depends partly on industry and possibly country) but it seems like - if successful - it would lead to the safest result for all involved.
Most banks have 3rd party APIs that allow service calls for read only access to a given account. Thus removing the need for a bolt on service to store credentials... Most times the best you get is an XML feed of transactions, balances...

If you're integrating with a financial institution that cant give u this. I'd go with paginated hash of the passwords stored in the data file with keys hashed in filed on the file system. I'd store the hash for the pages in a physical dongle attached to a server, with hardware discovery.

You could paginate the dongles daily too... There are some off the shelf dongles that do this quite nicely.