2

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 or false, 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.

  • "The user starts a new TLS connection through the proxy, which uses a different private key." - "private key" is used in context of public-key cryptography, i.e. with certificates. Maybe do you mean the (pre-)master secret of the TLS session? – Steffen Ullrich Dec 8 '17 at 19:03
  • Sorry about the terminology. Yes, I meant the master secret that can be used to decrypt the session. – ndbroadbent Dec 8 '17 at 19:17
  • I don't know about secure, but the UX is complex which introduces a lot of opportunities for the user to mess things up. And you also hope that the bank does not transmit anything of a personal nature in the proof session that might be considered private. Like overdue notices. – schroeder Dec 8 '17 at 21:43
  • That's very true. There would need to be an app or browser extension that makes the process just as easy as giving your username and password in plaintext. Also, since the user would be viewing the proxied session in their own browser, they could dismiss any notifications or visit a different page that only discloses the minimum amount of information. I've just updated the question with a more interesting idea under the notes, which would involve a non-interactive zero-knowledge proof. That way you could only reveal the bare minimum amount of information for any TLS session. – ndbroadbent Dec 8 '17 at 21:53
  • I'm confused why the standard "we deposited $0.xx in your account. Tell us the actual amount deposited" isn't sufficient. To me you are trying to fix a broken system that already has established alternatives – schroeder Dec 9 '17 at 1:06
1

I think that the mechanism could in theory work, provided that the user can trust it's bank that their site is setup in a way so that no sensitive information are transferred within the "proof" session. That means at least that only the information relevant to the proof are included in the proof session, that the HTTP session id can not be used by the third party and that no TLS session reuse is done, i.e. that the same key is not used to protect previous or following TLS sessions.

This means that not only the user needs special software to create the proof session but also that the bank needs to be setup in a way to securely support this proof. In my opinion this makes this concept too complex and too unreliable in practice.

  • Thanks for your answer! I've just checked a bunch of different banks, and it's pretty clear that clicking a "logout" button always invalidates the current session id, so that it can no longer be used. I think this would be true for the majority of websites. You're right that users will need some special software, but I don't think it's true that the bank needs to change anything. At least in all the cases I've checked, there doesn't appear to be any sensitive information in the cookies or HTML. It's just my personal details and account balances. – ndbroadbent Dec 8 '17 at 21:32
  • @ndbroadbent: note that the session id at the HTTP level is not the same as the TLS session. To cite myself: "...and that no TLS session reuse is done, i.e. that the same key is not used to protect previous or following TLS sessions.". Since TLS session reuse is commonplace because otherwise TLS performance sucks I doubt that it is disabled on these sites. "...and account balances" - I would consider this already too much information, i.e. more than needed to verify that you own the account. – Steffen Ullrich Dec 9 '17 at 5:19
0

I see a potential vulnerability, although I'm not sure myself whether it can really be executed. The risk is not on the client side, but on the third-party side. In fact, I had first added a comment, which I deleted afterwards, because I realized that I was wrong, and this got me thinking about this vulnerability. The comment I deleted, was, that you didn't need the third party proxy, but that you could, as a user, register the TCP flux yourself, and then send this record of TCP flux as a zipped file, together with the key establishment handshake, to the third party, as a "proof of past session". But then I realized that this is no proof, because the actual content of the session is encrypted in TLS with a symmetric key, so, you, as a user, could modify it as you'd like, too, because you too, have the symmetric key. You can also calculate all kinds of MAC with that key. If your bank sent you that you are long overdue on a negative balance during the session, you can modify this into an account display with 5 million dollars on your account. The certificate is from the bank, the negotiated symmetric key is true, but the content can be determined by not only the bank, but by you too. So I erased my erroneous suggestion.

However, I think one can do the same thing through the proxy. If you, as a user, set up a fake web socket on one of your machines, and instead of contacting the bank through the third party proxy, you contact your machine, which acts as a second proxy, and will contact the bank, you can do a MITM attack on your own TLS session with that proxy, because you know the symmetric key, and modify at your will, the content, just like in my erased comment. If the bank tells you you're overdue, you can modify this on the fly in your proxy, and show an account balance of 5 million dollars, which is the TCP stream that the third party will decrypt.

Of course, if the third party is attentive, it can see that the IP address you went to, doesn't correspond to a bank IP address. But it will have a correct certificate, and a correct key negotiation.

  • Oh you're right! That symmetric key issue is a real dealbreaker, so you have to use a proxy. The third-party would also have to ensure that the client connects to an IP address returned by DNS. It's unfortunate that TLS doesn't have a way to use asymmetric encryption for brief sessions. I'm trying to think if there might be any way to solve this, but it doesn't seem very likely. – ndbroadbent Dec 9 '17 at 10:31
  • Point is that in the end, the only security left is a hopefully correct DNS response... – entrop-x Dec 9 '17 at 10:45
  • I just realized that asymmetric encryption wouldn't help either. This just means that the server could encrypt some information that only the client would be able to decrypt, and vice versa. This is already the case when you have a key exchange and switch to symmetric encryption. So the server would just need to sign the data it sends with the private key for its SSL certificate. I don't know if this is already possible, but if not, it could be implemented as a plugin in Nginx or Apache. The plugin could generate a signature for the response body, and send that signature in a header. – ndbroadbent Dec 9 '17 at 10:49
  • I found the solution! There's a new specification for HTTP Signatures that will solve this problem. This means that a recorded TLS session can be non-repudiable, as long as the server sends signatures for the request and response. This also means that the third-party proxy is no longer necessary - A user can generate the proof on their own machine. – ndbroadbent Dec 9 '17 at 16:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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