Thanks to Tommy Mysk and Talal Haj Bakry of @mysk_co for the impetus and information behind this article. The duo describe themselves as “two iOS developers and occasional security researchers on two continents.” In other words, although cybersecurity isn’t their core business, they’re doing what we wish all programmers would do: not taking application or operating system security features for granted, but keeping their own eyes on how those features work in real life, in order to avoid tripping over other people’s mistakes and assumptions.
The featured image above is based on one of their tweets, which you can see in full below.
Twitter recently announced that it doesn’t think SMS-based two-factor authentication (2FA) is secure enough any more.
Ironically, as we explained last week, the very users for whom you’d think this change would be most important are the “top tier” Twitter users – those who pay for a Twitter Blue badge to give them more reach and to allow them to send longer tweets…
…but those pay-to-play users will be allowed to keep using text messages (SMSes) to receive their 2FA codes.
The rest of us need to switch over to a different sort of 2FA system within the next three weeks (before Friday 2023-03-17).
That means using an app that generates a secret “seeded” sequence of one-time codes, or using a hardware token, such as a Yubikey, that does the cryptographic part of proving your identity.
Hardware keys or app-based codes?
Hardware security keys cost about $100 each (we’re going by Yubikey’s approximate price for a device with biometric protection based on your fingerprint), or $50 if you’re willing to go for the less-secure sort that can be activated by the touch of anyone’s finger.
We’re therefore willing to assume that anyone who has already invested in a hardware security token will have done so on purpose, and won’t have bought one to leave it sitting idly around at home.
Those users will therefore already have switched away from from SMS-based or app-based 2FA.
But everyone else, we’re guessing, falls into one of three camps:
- Those who don’t use 2FA at all, because they consider it an unnecessary additional hassle when logging in.
- Those who turned on SMS-based 2FA, because it’s simple, easy to use, and works with any mobile phone.
- Those who went for app-based 2FA, because they were reluctant to hand over their phone number, or had already decided to move on from text-message 2FA.
If you’re in the second camp, we’re hoping you won’t just give up on 2FA and let it lapse on your Twitter account, but will switch to an app to generate those six-digit codes instead.
And if you’re in the first camp, we’re hoping that the publicity and debate around Twitter’s change (was it really done for security reasons, or simply to save money on sending so many SMSes?) will be the impetus you need to adopt 2FA yourself.
How to do app-based 2FA?
If you’re using an iPhone, the password manager built into iOS can generate 2FA codes for you, for as many websites as a you like, so you don’t need to install any additional software.
On Android, Google offers its own authenticator app, unsurprisingly called Google Authenticator, that you can get from Google Play.
Google’s add-on app does the job of generating the needed one-time login code sequences, just like Apple’s Settings > Passwords utility on iOS.
But we’re going to assume that at least some people, and possibly many, will perfectly reasonably have asked themselves, “What other authenticator apps are out there, so I don’t have to put all my cybersecurity eggs into Apple’s (or Google’s) basket?”
Many reputable companies (including Sophos, by the way, for both iOS and Android) provide free, trustworthy, authenticator utilities that will do exactly what you need, without any frills, fees or ads, if you understandably feel like using a 2FA app that doesn’t come from the same vendor as your operating system.
Indeed, you can find an extensive, and tempting, range of authenticators just by searching for Authenticator app in Google Play or the App Store.
Spoilt for choice
The problem is that there is an improbable, perhaps even imponderable, number of such apps, all apparently endorsed for quality by their acceptance into Apple’s and Google’s official “walled gardens”.
In fact, friends of Naked Security @mysk_co just emailed us to say that they’d gone looking for authenticator apps themselves, and were somewhere between startled and shocked at what they found.
Tommy Mysk, co-founder of @mysk_co, put it plainly and simply in an email:
We analysed several authenticator apps after Twitter had stopped the SMS method for 2FA. We saw many scam apps looking almost the same. They all trick users to take out a yearly subscription for $40/year. We caught four that have near identical binaries. We also caught one app that sends every scanned QR code to the developer’s Google analytics account.
As Tommy invites you to ask yourself, in a series of tweets he’s posted, how is even a well-informed user supposed to know that their top search result for “Authenticator app” may in fact be the very one to avoid at all costs?
Imposter apps in this category, it seems, generally try to get you to pay them anywhere from $20 to $40 every year – about as much as it would cost to buy a reputable hardware 2FA token that would last for years and almost certainly be more secure:
Many of these suspicious authenticator apps use this technique to trick users. After you finish the welcome wizard after the first launch, you get the in-app purchase view. And the x button to dismiss the view appears after a few seconds (upper right corner)#AppStore pic.twitter.com/sgxEo5ZwF0
— Mysk 🇨🇦🇩🇪 (@mysk_co) February 20, 2023
When we tried searching on the App Store, for example, our top hit was an app with a description that bordered on the illiterate (we’re hoping that this level of unprofessionalism would put at least some people off right away), created by a company using the name of a well-known Chinese mobile phone brand.
Given the apparent poor quality of the app (though it had nevertheless made it into the App Store, don’t forget), our first thought was that we were looking at out-and-out company name infringement.
We were surprised that the presumed imposters had been able to acquire an Apple code signing certificate in a name we didn’t think they had the right to use.
We had to read the company name twice before we realised that one letter had been swapped for a lookalike character, and we were dealing with good old “typosquatting”, or what a lawyer might call passing off – deliberately picking a name that doesn’t literally match but is visually similar enough to mislead you at a glance.
When we searched on Google Play, the top hit was an app that @mysk_co had already tweeted about, warning that it not only demands money you don’t need to spend, but also steals the seeds or starting secrets of the accounts you set up for 2FA.
Remember the secret string
6QYW4P6KWALGCUWM in the QR code, and the TOTP numbers
660680 that you can see in the images below, because we’ll meet them again later on:
Why seeds are secrets
Most app-based 2FA codes rely on a cryptographic protocol known as TOTP, short for time-based one-time password, specified in RFC 6238.
The algorithm is surprisingly simple, as you can see from the sample Lua code below:
The process works like this:
A. Convert the seed, or “starting secret”, originally provided to you as a base32-encoded string (as text or via a QR code), into a string of bytes [line 4].
B. Divide the current “Unix epoch time” in seconds by 30, ignoring the fractional part. The Unix time is the number of seconds since 1970-01-01T00:00:00Z .
C. Save this number, which is effectively a half-minute counter that started in 1970, into a memory buffer as a 64-bit (8-byte) big-endian unsigned integer .
D. Hash that 8-byte buffer using one iteration of HMAC-SHA1 with the base32-decoded starting seed as the key .
E. Extract the last byte of the 160-bit HMAC-SHA1 digest (byte 20 of 20), and then take its bottom four bits (the remainder when divided by 16) to get a number X between 0 and 15 inclusive .
F. Extract bytes X+1,X+2,X+3,X+4 from the hash, i.e. 32 bits drawn anywhere from the first four bytes (1..4) to the last-four-but-one bytes (16..19) .
G. Convert to a 32-bit big-endian unsigned integer and zero out the most significant bit, so it works cleanly whether it’s later treated as signed or unsigned .
H. Take the last 6 decimal digits of that integer (calculate the remainder when divided by a million) and print it out with leading zeros to get the TOTP code .
In other words, the starting seed for any account, or the secret as you can see it labelled in @mysk_co’s tweet above, is quite literally the key to producing every TOTP code you will ever need for that account.
Codes are for using, seeds are for securing
There are three reasons why you only ever type in those weirdly-computed six-digit codes when you you login, and never use (or even need to see) the seed again directly:
- You can’t work backwards from any of the codes to the key used to generate them. So intercepting TOTP codes, even in large numbers, doesn’t help you to reverse-engineer your way to any past or future logon codes.
- You can’t work forwards from the current code to the next one in sequence. Each code is computed independently, based on the seed, so intercepting a code today won’t help you logon in the future. The codes therefore act as one-time passwords.
- You never need to type the seed itself into a web page or password form. On a modern mobile phone, it can therefore be saved exactly once into the secure storage chip (sometimes called an enclave) on the device, where an attacker who steals your phone when it’s locked or turned off can’t extract it.
Simply put, a generated code is safe for one-time use, because the seed can’t be wrangled backwards from the code.
But the seed must be kept secret forever, because any code, from the start of 1970 until long after the likely heat death of the universe (263 seconds into the future, or about 0.3 trillion years), can be generated almost instantly from the seed.
Of course, the service you’re logging into needs a copy of your seed in order to verify that that you’ve supplied a code that matches the time at which you’re trying to log on.
So you need to trust the servers at the other end to take extra care to keep your seeds secure, even (or perhaps especially) if the service gets breached.
You also need to trust the application you’re using at your end never to reveal your seeds.
That means not displaying those seeds to anyone (a properly-coded app won’t even show the seed to you after you’ve entered it or scanned it in, because you simply don’t need to see it again), not releasing seeds to to any other apps, not writing them out to log files, adding them to backups or including them in debug output…
…and very, very definitely never transmitting any of your seeds over the network.
In fact, an app that uploads your seeds to a server anywhere in the wirld is either so incompetent that you should stop using it immediately, or so untrustworthy that you should treat it as cybercriminal malware.
What to do?
If you’ve grabbed an authenticator app recently, especially if you did it in a hurry as a result of Twitter’s recent announcement, review your choice in the light of what you now know.
If you were forced into paying a subscription for it; if the app is littered with ads; if the app comes with larger-than-life marketing and glowing reviews yet comes from a company you’ve never heard of; or if you’re simply having second thoughts, and something doesn’t feel right about it…
…consider switching to a mainstream app that your IT team has already approved, or that someone technical, whom you know and trust, can vouch for.
As mentioned above, Apple has a built-in 2FA code generator in Settings > Passwords, and Google has its own Google Authenticator app in the Play Store.
Your favourite security vendor probably has a free, no-ads, no-excitement code generator app that you can use, too. (Sophos has a standalone authenticator for iOS, and an authenticator component in the free Sophos Intercept X for Mobile app on both iOS and Android.)
If you do decide to switch authenticator app because you’re not sure about the one you’ve got, be sure to reset all the 2FA seeds for all the accounts you’ve entrusted to it.
(In fact, if the old app has an option to export your seeds so you can read them into a new app, you now know not only that you shouldn’t use that feature, but also that your decision to switch apps was a good one!)
QUANTIFYING THE RISK FOR YOURSELF
The risk of leaving your account protected by a 2FA seed that you think someone else might already know (or be able to figure out) is obvious.
You can prove this to yourself by using the TOTP algorithm we presented earlier, and feeding in [A] the “secret” string from Tommy Mysk’s tweet above and [B] the time he took the screenshot, which was 7:36pm Central European time on 2023-02-25, one hour ahead of UTC (Zulu time, denoted
Z in the timestamp below).
The stolen seed is: 6QYW4P6KWALGCUWM Zulu time was: 2023-02-25T18:36:00Z Which is: 1,677,350,160 seconds into the Unix epoch
As you might expect, and as you can match up with the images in tweet above, the code produces the following output:
$ luax totp-mysk.lua Tommy Mysk's code was: 660680
As the famous videogame meme might put it: All his TOTP code are belong to us.