Two-factor authentication mechanisms based on TOTP have become widespread in recent years. They are genuinely convenient for users, require no additional hardware, and are therefore often perceived as a "secure by default" solution. However, this is a common misconception. TOTP itself is not a security control — it is merely a cryptographic primitive used to build one. The actual security level is entirely determined by how this mechanism is implemented and integrated into the product: from code verification logic and attempt limits to error handling and its interaction with the rest of the authentication flow.

Example of Exploitation in a Zero-Protection Scenario

One of the most common TOTP solutions is a typical 6-digit RFC 6238 TOTP implementation (as used by apps like Google Authenticator). By default, it generates a six-digit code with a 30-second validity period, and it is often assumed that this alone is sufficient to ensure security. However, it is worth evaluating how secure such a mechanism actually is on its own — without any additional protective measures.

Probability of Brute-Forcing TOTP Without Server-Side Protection

Consider a standard TOTP configuration. The code consists of six digits, which means the total space of possible values is:

M = 1⁰⁶ = 1,000,000

Assume that within a single 30-second time window, an attacker can perform N code verification attempts. For example, if the server allows approximately 10 requests per second, then within one window, the attacker can make:

N ≈ 10 × 30 = 300 attempts

We assume that each attempt is an independent random guess and that the server provides no additional side signals .

Probability of Success Within a Single Time Window

The probability of guessing the correct code in a single attempt is:

1 / M

Accordingly, the probability of at least one successful guess within N attempts during a single 30-second window is:

P_window = 1 − (1 − 1/M)^N

For large values of M, this expression can be approximated as:

P_window ≈ N / M

For N = 300, we obtain:

P_window ≈ 300 / 1,000,000 = 0.0003 = 0.03%

This means that the probability of success within a single window is small, but it is not zero.

Accumulation of Probability Over Multiple Windows

Over a 24-hour period, the number of 30-second windows is:

k = (24 × 60 × 60) / 30 = 2880

The probability of at least one successful guess over k windows is:

P_total = 1 − (1 − P_window)^k

Using an exponential approximation, this can be rewritten as:

P_total ≈ 1 − exp(−k × N / M)

For the example above (N = 300):

• Over 24 hours: P_total ≈ 57.9%

• Over 48 hours: P_total ≈ 82.2%

• Over 72 hours: P_total ≈ 92.5%

This is a key point. It is more accurate to reason in terms of probability accumulation rather than "average brute-force time." In the absence of server-side protections, the probability of a successful guess becomes high within 1–3 days.

None

Impact of Allowing Adjacent Time Windows

Special attention should be paid to the handling of TOTP time windows. In practice, servers often accept not only the code from the current 30-second window, but also code from adjacent windows (for example, ±1 step) to compensate for clock drift. With such a configuration, a single verification attempt effectively covers multiple possible values. When a ±1 window tolerance is allowed, the number of valid codes increases threefold, which is equivalent to a threefold acceleration of online brute-force attacks. If strict attempt limits are not enforced, this configuration significantly reduces the effective strength of TOTP .

Key Takeaway

Even a small allowance for time drift can dramatically accelerate online brute-force attacks if there are no limits on the number of verification attempts and no correct server-side protection logic. Without proper controls, TOTP quickly degrades from a security mechanism into a probabilistic obstacle that can be overcome in practice.

These calculations are approximate and do not account for several real-world factors; however, they clearly illustrate the key conclusion: without protection or with incorrect implementation, a TOTP code can be brute-forced within a short timeframe (on the order of days). This is precisely why correct server-side implementation and additional defensive mechanisms are critical when using TOTP in real-world authentication systems.

Threat model

This article focuses on online attacks against TOTP verification endpoints, including distributed brute-force attempts and abuse of poorly designed recovery flows.

Phishing, malware, and full device compromise are out of scope.

The Meaning and Role of TOTP Systems

A TOTP mechanism does not make a system secure by its mere presence. Its effectiveness depends entirely on correct integration and supporting controls; when implemented incorrectly, it adds friction without eliminating real attack vectors.

TOTP as an Authentication Method

The first and most dangerous mistake is using a TOTP code as a replacement for a password, for example, in account recovery mechanisms. Even one-time codes, including TOTP, are fundamentally not designed for direct authentication without an additional factor. Due to the limited code length, the brute-force search space is finite, which means that with an incorrect implementation, brute-force attacks become a real possibility. A correct and significantly more secure approach is to use TOTP strictly as an additional verification factor, and then initiate a password reset via a one-time link sent to the associated email address. This design sharply reduces the risk of brute-forcing and eliminates the possibility of account recovery through code guessing alone.

Rate Limiting as the Only Security Mechanism

Another common mistake is assuming that standard rate limiting (for example, 4–5 attempts per second) is sufficient to secure TOTP. While such limits reduce the brute-force rate, they do not eliminate the attack vector. Distributed attacks easily offset per-source limits by spreading attempts across multiple devices or nodes, keeping the aggregate attempt volume high enough to brute-force the code.

Rate limiting remains an important supporting control, but relying on it as the primary or sole defense is fundamentally insufficient. Effective protection requires combining it with additional mechanisms that enforce cumulative limits and state across attempts.

Why CAPTCHA Is Not an Absolute Security Measure

Similar to rate limiting, CAPTCHA is often mistakenly treated as a standalone security control. In practice, CAPTCHA-solving services and farms allow attackers with sufficient resources to continuously obtain valid tokens, increasing cost and complexity but not eliminating the attack vector.

CAPTCHA should therefore be used only as a supporting mechanism. A common implementation flaw is allowing CAPTCHA tokens to have a long lifetime or failing to bind them to a specific verification request. In such cases, tokens can be reused or replayed outside their original context, significantly reducing their effectiveness.

None

Binding Verification Attempts to an Identifier (ID)

Another common mistake is binding attempt limits to a verification identifier such as a request ID, temporary token, or session identifier. If such identifiers can be regenerated, each verification attempt is effectively treated as a new one, preventing meaningful accumulation of state and rendering brute-force protection ineffective.

As a mitigation, limits are often bound to the client's IP address. While this increases attack cost, it does not eliminate the attack vector: IP-based restrictions are inherently bypassable and merely raise the price of the attack rather than preventing it.

Global Account Lockout as a Denial-of-Service Vector

Another mistake is the incorrect use of blocking mechanisms around TOTP verification. While blocking parallel attempts and temporary lockouts can be justified in certain scenarios, unjustified or poorly scoped implementations can introduce a denial-of-service vulnerability.

In particular, global account lockout or rigid blocking of parallel TOTP entry attempts allows an attacker to prevent legitimate access by repeatedly triggering verification failures, without ever compromising the account itself. In this case, an authentication control is transformed into an availability issue.

Blocking mechanisms, therefore, require careful design and tuning. In most cases, it is preferable to apply adaptive rate limiting to the source of attempts — such as IP address, device, or other stable identifiers — combined with progressively increasing delays between attempts (for example, 30 seconds, 1 minute, 5 minutes), rather than locking the account globally.

Security Model Checklist

Security should not be built around a single factor or a single mechanism. A robust security model relies on a combination of multiple independent controls, each compensating for the weaknesses of the others. In addition, the system should always provide an alternative access verification path that preserves both security and availability in the event that one factor fails or is compromised.

1)Alternative methods of two-factor authentication

In addition to TOTP, the system should provide an alternative method for verifying login via email. The most secure option is an email containing a one-time link rather than a numeric code.

2)Correct use of captcha and rate limits

CAPTCHA and rate limiting should be treated as supporting security mechanisms rather than as the foundation of the security model. They increase the cost and complexity of attacks but do not eliminate their fundamental feasibility. When CAPTCHA is used, it is critical to strictly bind the CAPTCHA token to each verification request, as the absence of such binding or an excessively long token lifetime effectively reduces the protection to a minimum.

3)Use blocking carefully

Lockout mechanisms should primarily be applied to the source of attempts — such as the IP address, device, or another stable identifier — rather than to the account itself. This approach allows attacks to be effectively constrained without denying access to legitimate users. When alternative identity verification methods are available, it is acceptable to apply a temporary global block specifically to TOTP verification, rather than to the entire 2FA mechanism.

None

Conclusion

It is important to understand that a TOTP mechanism is a tool for building security, not security in itself. When integrated correctly, it significantly increases a system's resistance to attacks. When used incorrectly, however, TOTP merely adds friction to two-factor authentication or other technologies into which it is embedded, without addressing core attack vectors or providing real security.