There are many financial services that can verify a user's bank account by asking for their username and password, and signing in on their behalf. Some examples are Coinbase and TransferWise.
I've come up with a way for a user to verify their bank account details without ever providing their username and password to a third party. I would like to know if there are any security flaws with the following protocol:
- The third party service starts a proxy server that records all traffic.
- The user establishes a TLS connection through the proxy, and verifies the bank's SSL certificate.
- The user signs in using their username and password, and saves their session cookie.
- The user starts a new TLS connection through the proxy, which uses a different master secret.
- The user uses their current session cookie to fetch their account details through the proxy.
- The user signs out and invalidates the session cookie.
- The user sends the final TLS connection's master secret to the third party service.
- The third party service is now able to decrypt the HTML and verify the user's details, such as their full name, phone number, and account balances.
Notes:
- If a bank allows a session cookie to be used from multiple IP addresses, the user could just sign in and out on their own machine.
- The user would be viewing the proxied pages on their own machine, so this would also work with two-factor authentication.
- Some online banking websites may not properly invalidate session cookies when a user signs out. However, most (if not all) banks expire a session after 10-15 minutes of inactivity, so the user can just wait for the session to expire before revealing the private key.
- The page HTML could leak more data than necessary. There would be various ways to solve this for different banks. Many banks provide an API for their mobile apps, so you could just proxy some specific API requests to only reveal the necessary information.
- Instead of sending the private key and allowing a third-party to decrypt all of the HTML and cookies, it might be possible to create an encrypted boolean circuit that provides a zero-knowledge proof for the recorded TLS session. The third party could run a computation that verifies the TLS handshake and certificate, decrypts the URL and HTML, then checks for the presence of certain strings to verify the user's account details. The result of the circuit is either
true
orfalse
, and the third party wouldn't be able to discover any other information about the encrypted session. Alternatively, the circuit outputs could even be the strings of your full name, phone number, and checking account balance. I'm going to try to investigate this approach with the libsnark library, because it's such a fascinating idea!
One way to implement this might be to create a WebKit-based browser application that users can download and install. The app could set up a protocol handler in their browser, so that the app opens whenever the user clicks on a URL like <verification scheme>://domain/path
. The app would work with any website, but it could also use preconfigured recipes for different banks.
This could also be implemented directly in Firefox and Chrome, but that's not very likely. There's also much better ways to do this. Some modern banks can provide an OAuth token with limited read-only permissions. A bank could even use public key cryptography to just sign your account details using their private key (maybe the private key for their current SSL certificate.)
I think the technique described above might be useful, since it can work for any website (not just banking.) But please let me know if you can spot any security issues here. I'm sure I've misunderstood something about TLS, or maybe there's an even easier way to do this.