Is 6 digits really enough for an OTP code?

  • SpinRite v6.1 Release #3
    Guest:
    The 3rd release of SpinRite v6.1 is published and may be obtained by all SpinRite v6.0 owners at the SpinRite v6.1 Pre-Release page. (SpinRite will shortly be officially updated to v6.1 so this page will be renamed.) The primary new feature, and the reason for this release, was the discovery of memory problems in some systems that were affecting SpinRite's operation. So SpinRite now incorporates a built-in test of the system's memory. For the full story, please see this page in the "Pre-Release Announcements & Feedback" forum.
    /Steve.
  • Be sure to checkout “Tips & Tricks”
    Dear Guest Visitor → Once you register and log-in please checkout the “Tips & Tricks” page for some very handy tips!

    /Steve.
  • BootAble – FreeDOS boot testing freeware

    To obtain direct, low-level access to a system's mass storage drives, SpinRite runs under a GRC-customized version of FreeDOS which has been modified to add compatibility with all file systems. In order to run SpinRite it must first be possible to boot FreeDOS.

    GRC's “BootAble” freeware allows anyone to easily create BIOS-bootable media in order to workout and confirm the details of getting a machine to boot FreeDOS through a BIOS. Once the means of doing that has been determined, the media created by SpinRite can be booted and run in the same way.

    The participants here, who have taken the time to share their knowledge and experience, their successes and some frustrations with booting their computers into FreeDOS, have created a valuable knowledgebase which will benefit everyone who follows.

    You may click on the image to the right to obtain your own copy of BootAble. Then use the knowledge and experience documented here to boot your computer(s) into FreeDOS. And please do not hesitate to ask questions – nowhere else can better answers be found.

    (You may permanently close this reminder with the 'X' in the upper right.)

SecretStasher

Member
Feb 14, 2023
11
3
In SN-909, Steve was suggesting that, for an OTP code, 6 digits was sufficient because the code is constantly changing (unless I was misunderstanding).

I'm not really seeing how this is the case unless other security measures are also in place. I've written programs to run simulations myself, and based on the results, it looks like a moving target roughly doubles the difficulty of brute force. Specifically, if I write a program to make 999,999 guesses on a 6 digit number where the target number changes every guess, there will be at least one correct guess roughly 50% of the time (vs 100% of the time on a stationary target).

Based on 1000 guesses per second (which is what Password Haystacks assumes for an online attack scenario), an attacker would have a 50% chance of guessing correctly in 18.52 minutes - not exactly great security.

Now, I do still see one advantage here to the moving target vs a stationary target, and that is that when the attacker guesses correctly, it only gets the attacker one single logon rather than actual knowledge of the password because the next logon, the OTP code will have changed. But if that single logon grants the attacker the keys to the kingdom, it can still be devastating.

Possible mitigations might be rate limiting, account lockout on incorrect guesses, or reauthentication being required after logon, but I don't think we can assume that these mitigations are in place unless they are specifically mentioned.

Am I missing something?


EDIT: Minor grammor and spelling corrections
 
Last edited:
Here are some random thoughts. I'm not a cryptography expert so others jump in. For the code to unlock my phone, for example, which doesn't change, the phone will do some sort of lockout after 10 wrong tries. If I'm logging into the bank and I get the code either by email or by a 2FA app, the website SHOULD lock me out after just a few tries. In most cases, an OTP is the 2nd factor, not the only factor. If you're using a long random password stored in a properly operating password vault and long padded master password, it should be VERY unlikely that anyone is going to crack your website login password. But, say they did. They put in your user id and your correct password. The bank asks for the 2FA. There are one million permutations of a 6 digit number, including 000000. If the website locks them out after 10 wrong tries, they still have only a 1 in 100,000 chance of getting in. If they do get in, and go away and get coffee, the website will probably time out and kick them out after 15 minutes. Then they have to start over. So, it seems to me that a 6 digit OTP as a 2ND factor should be good enough. If it's the ONLY factor, then it's pretty weak. If I said something wrong in there, y'all can correct me.

May your bits be stable and your interfaces be fast. :cool: Ron
 
So, it seems to me that a 6 digit OTP as a 2ND factor should be good enough. If it's the ONLY factor, then it's pretty weak. If I said something wrong in there, y'all can correct me.

I have seen OTP devices where, in order to generate the OTP code, it requires a PIN or password first be first entered on the OTP device itself, so they call it two factors in one:
  • Something you know because you need the PIN or password to generate it.
  • Something you have because you have to have the device itself to generate it.
Although this may be two factors, it's still only a 6 digit code protecting both.

That said, these same cases that I am thinking of do do things like temporary lockouts if you enter 5 incorrect PINs, which would slow down the guessing a lot.
 
Although this may be two factors, it's still only a 6 digit code protecting both.
I think I'd call that a single factor, like you said. I consider 2FA that the ATTACKER has to have my password and OTP code for example. Others may think differently though.

May your bits be stable and your interfaces be fast. :cool: Ron
 
A six digit OTP code is fine given that they expire every 30 seconds. While there is a window of maybe 3 to 5 minutes total (to allow for clock skew) the site accepting the input should be designed to not allow bulk tries. In particular, against a given (30 second) code, it should not allow more than two tries, before forcing a delay to a new code... and if you get it wrong too many times, it should force you to start your whole login over from the password.
 
  • Like
Reactions: Brian Gregory
A six digit OTP code is fine given that they expire every 30 seconds. While there is a window of maybe 3 to 5 minutes total (to allow for clock skew) the site accepting the input should be designed to not allow bulk tries. In particular, against a given (30 second) code, it should not allow more than two tries, before forcing a delay to a new code... and if you get it wrong too many times, it should force you to start your whole login over from the password.

I think in your example, the primary protection is coming from the fact that you're only allowed to guess 1-2 times every 30 seconds, not from the fact that the code is changing every 30 seconds.

Per the simulation that I wrote, even if every single guess expires the code, an attacker capable of guessing 1000 times per second (the speed of an online attack on on Password Haystacks) would have a roughly 50% chance of guessing right against a constantly changing code in 18.52 minutes.

Limiting it to two guesses every 30 seconds, on the other hand, it would take 173.61 days to get a roughly 50% chance of guessing right. OK protection maybe, but not the centuries we we tend to expect from a long, strong password.
Still suggests to me that you'd want to either use this only as a second factor or have a decent length account lockout (or both!)
 
I don't think you're understanding the situation. It's NOT a password, it's not intended to be treated like a password, and it's not a replacement for a secure password. It's intended to prove you are the password holder, as a second factor. In order to be able to even use the TOTP the attacker already has to have your password. If you keep bashing the site, the site should be smart enough to eventually lock the account. Because of how the TOTP code is derived, there is no benefit to guessing randomly, your odds remain 1 in 1,000,000 for EVERY 30 seconds. You might as well just always guess 123456 and hope you get the one time that is actually the code.
 
  • Like
Reactions: SeanBZA
This is probably not typical, but part of the login process at work follows. They use Microsoft Authenticator which requires a password to authenticate on the laptop Once done it posts a 2 digit code on the laptop which must be entered into the authenticator app on my phone. Once entered, the authenticator on the phone needs to be unlocked with a PIN. Login procedes from there. Admittedly it is a pain in the butt logging in (there is more to the process than that) but it seems pretty secure with multiple passwords, PINs, and time outs. Some applications require security measures like that, but I don't think such measures are needed for personal use. For myself I recently started using a Yubikey and setting up accounts that can use it to do so. Even with that there are 1 or 2 accounts where the logins are only in my head.

I use Bitwarden as my primary manager, but I also use the portable version of Password Safe as it's backup and to keep a couple things not in BW. I may be wrong (If so let me know) but I think that is a pretty secure system. Of cause passwords are long and most of them random.
 
Assuming e.g. Google Authenticator, it produces 6-digit codes every 30 seconds. Allowing for being a minute or so off, that is still a much small window than the 18 minutes stated above. Along with a random, long password for the site itself, I feel pretty comfortable with those odds. That said, my critical resources (email in particular) are protected with dual Yubikeys (one is a backup for the other in case of a physical failure - remember 2 is 1, 1 is none).
 
To summarise what I'm seen so far, there are two general reasons the people are saying that a 6 digit OTP code could be safe:
  1. Because of other security measures deployed in addition to the OTP code (eg. rate limiting on guesses, lockouts after a certain number of guesses, deployment of another factor such as a password alongside it).
  2. Because the OTP code changes every 30 seconds or so.
I agree completely that point #1 absolutely makes this safe.

However, I haven't yet seen any points that makes #2 do any more than roughly double the difficulty of brute forcing the code.

Here's an experiment that people can try. Do each of the following multiple times.
  1. Flip two coins twice. Check whether, at least once, you got the same outcome on both coins. This will happen at least once roughly 75% of the time.
  2. Roll two 6-sided dice, six times. Check whether, at least once, you rolled doubles. This will happen at least once roughly 58% of the time.
  3. Roll two 100-sided dice, 100 times. Check whether, at least once, you rolled doubles. This will happen at least once bit more than 50% of the time.
What you will find if you do all four of the above experiments is that, as the number of possibilities on each die (and the number of allowed guesses) increases, the odds of getting doubles approaches (but never goes below) 50%. If you roll two 1,000,000 dice 1,000,000 times, you have a roughly 50% chance of rolling doubles at least once.

Now consider that one of the dice (or coins) represents your random guess, and the other die (or coin) represents correct OTP code. Even though the correct OTP code is changing on every single guess, you still have a 50% chance of guessing right in 1,000,000 tries.

So, from what I'm seeing, if the only thing protecting a site is a 6 digit OTP code, randomly guessing 1000 guesses per second will give you a 50% chance of guessing correctly within 18.52 minutes. And this is the case even though the code changes every 30 seconds (and would even be the case if the code changed every 0.1 seconds).

As mentioned above, if there are other things protecting the website such as a rate limiting on guesses, lockouts after a certain number of guesses, deployment of another factor such as a password alongside it, or reauthentication post-logon, this could be safe.
 
Why are you assuming the 6-digit OTP is the only thing protecting a site in the first place? In almost all cases, the flow is: username/email and password, then the 6-digit code. I only say almost all cases because there is a site I use that ask for all three at once, so the form is username, password, OTP code, and a trust checkbox (so the next login attempt will not show the OTP field by default, cookie expires in 7 days, or something the site tracks with the cookie is changed, so a browser update can shorten the time before you have to use the OTP again)
 
Why are you assuming the 6-digit OTP is the only thing protecting a site in the first place?
I have actually seen a system where the only two credentials required to log on are a user ID and a 6 digit OTP code. The OTP code comes from a mobile device where you have to enter a PIN into the device to make it generate the OTP code, so they claim that the device itself provices both "Something you know" (the PIN for the OTP device) and something you have (the OTP device itself). But the only thing you actually type into the browser is the 6 digit OTP code itself.

That said, the system does have other mitigations in place, such as rate limiting on guesses and account lockout on too many incorrect guesses.

So in the end, this is basically just a hypothetical: in the total absence of all other protections, is a 6 digit OTP code that changes every 30 seconds really better at preventing a single fraudulent logon than a password that isn't long or random enough? And it seems like the answer is no - odds are, you could actually brute force a 6 digit OTP code that changes every 30 seconds faster than you could a 7 digit password that never changes.
 
You should RUN, not walk, away from this site
I agree with what @PHolder said. That is weak security. Having said that, there are still a million permutations of 6 digits. If the website throws an attacker out after 10 wrong attempts, he still only has a 1 in 100,000 chance of getting in. Note that it's totally different if the attacker stole a database and does an offline crack attack versus an online attack. What the OTP does do is help prevent replay attacks. Let's say someone looked over your shoulder and saw your OTP code, or they snooped it from the wifi through the air. If they wait more than 30 seconds to try to get in, it won't work. Also, for legitimate users it's highly unlikely anyone will erroneously get in using the normal method. You have to have your phone and you have to know your pin. Anyone else that uses the same site normally without your phone and knowing your pin won't get in. It all depends on the vector being attacked. It is true that normal users have to have something they have and something they know, WHEN going through normal channels. But, an attacker won't necessarily go through normal channels. He might rent a bot net and try every one of the 1 million codes by doing 10 each from a different IP address. Or he might be able to do an SQL injection attack and bypass the rate limiter. It also occurs to me that there can only be the number of failing login codes equal to 1 million minus the number of users. If I truly understood you right, that the only login the SITE requires is the 6 digit code, and if it had 1 million users, then typing in ANY 6 digit code would get you into somebody's account. So, yeah, LAME.

May your bits be stable and your interfaces be fast. :cool: Ron
 
Last edited:
If the website throws an attacker out after 10 wrong attempts, he still only has a 1 in 100,000 chance of getting in.

What the OTP does do is help prevent replay attacks.
Yes, agree with all of that.

The hypothetical scenario we are talking about is a pure brute force attack where the only thing protecting the website is a six digit OTP code that changes every 30 seconds, and what we are trying to prevent is a single fraudulent logon. In this scenario, a 7 digit, pure numeric password that never changes would be stronger than the 6 digit, pure numeric OTP code that changes every 30 seconds, although both are terrible protection.

The 6 digit OTP code does prevent replay attacks where the 7 digit password does not.

And locking the user out after 10 invalid attempts will add more security to the 6 digit OTP code than the 7 digit pure numeric password because the lockout would invalidate all previous guesses on the OTP code.
 
  • Like
Reactions: rfrazier
Whilst we may all be arguing from a security point of view on whether this can be hacked, decisions on the login security are made by the site owner. In many cases, I suspect they have decided that a 6 digit OTP is "enough", any more will drive customers away. The cost of losing business outweighs the cost of any losses caused by insufficient security.
 
The odds of rolling doubles on 2 100-sided dice are 1/100 or 1%. This is because there are 100 ways to roll doubles on 2 100-sided dice: a 1 on both dice, a 2 on both dice, …, a 100 on both dice. The total number of possible outcomes is 100 x 100 = 10,000, so the probability of rolling doubles is 100/10,000 = 1/100. This formula can be generalized to any number of sides on the dice: the probability of rolling doubles on 2 n-sided dice is 1/n.
 
The odds of rolling doubles on 2 100-sided dice are 1/100 or 1%. This is because there are 100 ways to roll doubles on 2 100-sided dice: a 1 on both dice, a 2 on both dice, …, a 100 on both dice. The total number of possible outcomes is 100 x 100 = 10,000, so the probability of rolling doubles is 100/10,000 = 1/100. This formula can be generalized to any number of sides on the dice: the probability of rolling doubles on 2 n-sided dice is 1/n.
You might want to review your statistics. The odds of rolling doubles on 2 n-sided dice is 1/n². 1/n to roll the number on the first die x 1/n to roll that same number on the second. 1/n x 1/n = 1/n².

[Edit: I was corrected in a subsequent comment. I was thinking in terms of rolling a double of a specific number, not any possible combination of of doubles.]
 
You might want to review your statistics. The odds of rolling doubles on 2 n-sided dice is 1/n². 1/n to roll the number on the first die x 1/n to roll that same number on the second. 1/n x 1/n = 1/n².
Not quite actually. I'm going to switch this to 6 sided dice because it's easier to think in terms of 6 sided dice than 100 sided dice.

If we specifically want to check the odds of rolling double 6's on two 6 sided dice, you would be right.
  • Odds of rolling a 6 on the first die is 1/6
  • Odds of rolling a 6 on the second die is 1/6
  • Odds of both is (1/6) * (1/6) = 1/36.
However, we're not talking about double 6's here - we're talking about doubles of any number, which increases the odds:
  • Odds of rolling any number on the first die are 6/6
  • Odds of rolling the same number on the second die as we rolled on the first die (whatever that number was) are 1/6
  • Odds of both are (6/6) * (1/6) = 1/6
So, the odds of doubles where we don't care what number the doubles are would in fact be 1/6 as @Barry Wallis suggested.

This all assumes that you only roll once. If you roll multiple times, the odds increase, which was the point of the initial post. :)

EDIT: Added the comment about multiple rolls.
 
Last edited:
  • Like
Reactions: Greg S
Guys...

(I'm here only because I received one of those "See what you've missed" eMails from the forum and I noticed this thread.)

I'm right in the middle of working on SRv6.1, so I did not read all of this thread. But the one thing I didn't notice during an admittedly quick scan was that the BIG difference is that it's not possible to brute force thousands of these guesses (or really any guesses) because each guess must be vetted by the remote site. If you've ever mistyped one of these 6-digit codes, you enter it, submit the reply, and the site replies, telling you that it's wrong.

Someone noted up-thread that a website ought to not prevent endless guessing for a user, and that's true. But given the changing code every 30 seconds, and the typical site response turn-around, brute forcing OTP's is not practical. :)
 
  • Like
Reactions: Barry Wallis