3

I recently had a look at implementing the swedish BankID identification system for an app.

A prerequisite is that a client certificate is installed on our backend, which authenticates requests from our backend server.

Briefly, the flow looks like this when signing in to our app (the "client app") on a device and using another device (phone/tablet) to authenticate the user.

  • The client app sends an auth request to our backend.
  • Our backend sends an auth request to BankID.
  • We get a reply containing, among other things, a qrStartToken and qrStartSecret which are used to generate QR codes that the user must scan with the BankID app on their phone/tablet.
  • The response also includes autoStartToken, which identifies the "session" in subsequent calls to the BankID API (a session lasts 30 seconds).
  • The client app keeps making collect requests (via our backend) every 2 seconds, and when they have scanned the QR code the response will contain the status"complete", which means they are logged in.
  • The QR codes must be regenerated on our backend using the qrStartToken, qrStartSecret and number of seconds since the response from the auth request. Hence the phrase "animated QR codes".

Until recently, the QR code was static and was retrieved by making a request to the BankID API and supplying the autoStartToken (the session identifier). This has been deprecated, and apps should now use the "animated" QR codes, which are regenerated every second.

The reason BankID introduced the QR code system in the first place was that attackers would call unsuspecting victims, claiming they were from the bank or some other "authority" and telling the victim something along the lines of "We noticed that someone tried to hack into your bank account. Could you please log in using your BankID and verify if there are any suspicious transactions?". The victim would then start logging in to their account, but what they didn't know was that the attacker had already started logging in to their account on their computer a few seconds before them, so the "session" that the victim authorized in the BankID app on their phone was actually the attackers session! The QR code solves this by requiring visual access to the "session" (i.e. scanning the QR code in your desktop browser with the BankID app on your phone).

So, what I'm a bit curious about is what the "animated" QR code system improves? The static QR codes require only the autoStartToken, and the animated ones require qrStartToken and qrStartSecret + time of auth response as well. However, these are all received by the backend in the same response. So it seems to me that if an attacker could somehow get their hands on a autoStartToken (within its 30 second TTL), they could also get their hands on the other variables. In any case, it would have to be a far more advanced attack than the "phone scam" explained above to be able to get access to the response from the BankID API.

Can someone explain what type of attack the animated QR codes actually prevent, that the static QR codes are vulnerable to?

Magnus
  • 213
  • 1
  • 5
  • What was the expiry time of static QR code? WhatsApp web and Signal multi-device also use dynamic QR codes so that the attacker cannot plan long term attack to phish accounts. – defalt Nov 05 '21 at 16:48
  • I believe the static QR codes expired after 30 seconds, since that is how long you have to scan the QR code before the `collect` call would return the status `"failed"` to inform the client that the user didn't complete the authorization. – Magnus Nov 05 '21 at 18:28
  • So it's just an architectural change. Instead of API returning the QR code, now javascript is dynamically updating the QR code. I don't see any security design decision behind this. – defalt Nov 05 '21 at 18:46
  • I also wonder what the reason is to introduce animated QR codes, I could understand if they just want to move the responsibility of generating the QR code image to the RP, but why make it animated? – Axel Kennedal Feb 09 '22 at 13:55

0 Answers0