Breaking a TOTP?

Breaking a TOTP?


This post is written to raise awareness of the possible vulnerabilities of RFC 2638. Any code provided here is not intended to be used for malicious purposes and is merely a proof-of-concept and/or example to aid the understanding of the article.

RFC 2638: What is it?

In their words,

This document describes an extension of the One-Time Password (OTP)
algorithm, namely the HMAC-based One-Time Password (HOTP) algorithm,
as defined in RFC 4226, to support the time-based moving factor. The
HOTP algorithm specifies an event-based OTP algorithm, where the
moving factor is an event counter. The present work bases the moving
factor on a time value. A time-based variant of the OTP algorithm
provides short-lived OTP values, which are desirable for enhanced
security.

In simpler terms, offline one-time passwords are generated using a secret and a counter, as seen in RFC 4226:

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

Where K is the shared secret between client and server, and C is a 8-byte counter value, the moving factor.

Now how do we generate a time-based one-time password (TOTP) using RFC 4226?

How do we know the counter value?

That’s where RFC 2638 comes in. To determine the counter value, we simply divide the Unix Timestamp by the time step as seen in RFC 6238:

Basically, we define TOTP as TOTP = HOTP(K, T), where T is an integer
and represents the number of time steps between the initial counter
time T0 and the current Unix time.

More specifically, T = (Current Unix time – T0) / X, where the
default floor function is used in the computation.

Then we plug that into RFC 4226, and viola! We’ve just calculated our very own TOTP code!

The Vulnerability

While you may not realize immediately, with just two TOTPs and the timestamp they were captured in, we can crack the secret.

Wait, isn’t it SHA encoded?

Exactly, and that’s why we’re going down a different route. If we can’t reverse it, then maybe we can brute force it?

Calculating the secret ourselves

Brute forcing billions of TOTPs would be as foolish as trying every possible key to unlock a door.

So what if we do it the opposite way? Instead of trying every TOTP live, perhaps we could first calculate all the possible TOTPs at a given timestamp and capture the ones that match the TOTP “stolen”.

But you’ll still have thousands of possibilities

That’s where the second TOTP comes in, we can use the second TOTP to narrow down the possible secrets to a single digit, to a single secret. There’s two ways to approach this:

1. The Barbaric Way
Re-run all the billions of possible combinations again and see which ones match, effectively doubling the compute time.

2. The Smarter Way
Calculate TOTPs for each of the possible secrets at the timestamp when the second TOTP was “stolen”, adding nothing more than 10 seconds and a few thousand calculations.

I’m no genius but the latter seems like a better choice.

Always follow the RFC requirements

As written in Section 4 of RFC 4226,

R6 – The algorithm MUST use a strong shared secret. The length of
the shared secret MUST be at least 128 bits. This document
RECOMMENDs a shared secret length of 160 bits.

In other words, the secret must be no less than 16 characters.
While this helps mitigate the vulnerability, one day this will not be enough.

The logistics behind this

While performing billions of calculations can be both time and resource-intensive, Moore’s law has shown us that with the ever-increasing computational power/performance of modern computers and supercomputers, every year this vulnerability will only grow larger and larger, and will only cause more harm.

Try It Yourself: The Code

Here’s a repository I’ve put together previous to illustrate this vulnerability.

As of now, on my consumer-grade desktop, I can crack a 5 character secret in less than 3 minutes.

How’d I Do?
Feel free to leave a comment!



Source link
lol

By stp2y

Leave a Reply

Your email address will not be published. Required fields are marked *

No widgets found. Go to Widget page and add the widget in Offcanvas Sidebar Widget Area.