Mastodon: 2FA recovery codes shouldn’t be regenerable

Created on 26 Jun 2017  Â·  4Comments  Â·  Source: tootsuite/mastodon

With 2-factor authentication, there are obviously more ways to be unable to login (like if you’re on your front door and you forgot your keys) than without. That means more human mistakes, and more users complaints/issues. So implementing recovery codes has been a convenient way to provide secure login even if they lost their phone/keys/whatever.

Recovery codes serve as a list of single-use 2FA codes, that the user has to store securely when 2FA is activated, so, if or when the secret is lost or forgotten (broken phone, for example), they can login once, and deactivate 2FA, or regenerate the token. The whole point of recovery codes are that the list is small (but sufficient to prevent basic mistakes) so the attack surface is minimal, and that those codes are kept secret after generation.

Mastodon currently provides a way to regenerate the recovery codes on demand, without password confirmation. This is a security flaw, as anyone accessing an unlocked computer can regenerate, and store, a new list of recovery codes (thus making pretty useless the usage of 2FA). In this case, the attacker, given they know the password (because, you know, it’s hunter2 — just kidding, don’t use it —), they’re able to login at any time (which is pretty bad for TOTP), and do anything to the account.
Even without password access, a rogue recovery codes regeneration causes the user to lose possibility to login entirely if they lose the 2FA secret.

There is also an UX issue here: there is no way for a user to know if their codes are the latest generated, and misclicking the "regenerate" button can happen, immediately disabling old codes (and the user may not have the reflex to store/print those and revoke the obsolete ones).

So, basically, the problem is that a user can regenerate the recovery codes list. Adding password confirmation should very slightly increase security, but it’s not a serious workaround.

My suggestion would be to completely remove this regeneration feature.


  • [X] I searched or browsed the repo’s other issues to ensure this is not a duplicate.
  • [X] This bug happens on a tagged release and not on master (If you're a user, don't worry about this).
fit for beginners security suggestion

Most helpful comment

Adding password confirmation should very slightly increase security, but it’s not a serious workaround

Every major 2fa provider (Google, Github, Facebook) allows you to view your current recovery codes, and to optionally regenerate them.

This should be behind a confirmation step, certainly, and it's a bug that it isn't, but there's no security reason to remove the feature altogether.

All 4 comments

Adding password confirmation should very slightly increase security, but it’s not a serious workaround

Every major 2fa provider (Google, Github, Facebook) allows you to view your current recovery codes, and to optionally regenerate them.

This should be behind a confirmation step, certainly, and it's a bug that it isn't, but there's no security reason to remove the feature altogether.

I'm interested in taking a stab at this. Do you think asking the user to confirm their password is enough, or should the user be sent an email with a confirmation link? I lean towards the latter.

If that's the case, could Devise's Confirmable module do the heavy lifting for us? Maybe make a new model (RecoveryResetConfirmer?) so the sign-up confirmation stuff doesn't conflict?

I might get started with that approach, but any thoughts or advice would be appreciated. I've never worked with this codebase before, and it's bigger than any rails app I've contributed to, so I'd love to know if I'm heading in a bad direction.

Do you think asking the user to confirm their password is enough, or should the user be sent an email with a confirmation link? I lean towards the latter.

I would stick to just the password. Email address changes are possible with just the password, so the confirmation could easily be bypassed. Requiring access to the current address in order to change an account's email address is problematic in cases where access to that inbox is lost.

Most implementations I'm aware of gate 2FA settings behind the user's password and nothing else, assuming an existing session created at some point using both factors, so I think that's good enough for us.

An alternative that would add some value would be to send an email when 2FA settings are changed. That helps with timely detection of account compromises. The email change bypass can be mitigated by sending an email to the old email address when the address is changed (a notification, not confirmation, perhaps with instructions to contact the instance admin in case of a compromise.) This could be done separately at some point in the future - I don't think it should be a blocker.

Hay I was wondering if there any way I can revive my 2fa codes back or have it restored I no longer have the same phone when I was given the code

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Lewiscowles1986 picture Lewiscowles1986  Â·  3Comments

selfagency picture selfagency  Â·  3Comments

marrus-sh picture marrus-sh  Â·  3Comments

KellerFuchs picture KellerFuchs  Â·  3Comments

golbette picture golbette  Â·  3Comments