Security Tip: Timebox for Timing Attacks

[Tip#38] Laravel is full of little helpers and features, and the Timebox is one that's often overlooked.

Security Tip: Timebox for Timing Attacks

We’ve talked about timing attacks before, back in In Depth: Timing Attacks and Security Tip: Leaking Model Existence, and back when I wrote them, there wasn’t really a good default solution to defending against them in Laravel. I even said that it’s a difficult problem to solve in general, which is still true, but there are steps you can take to make it harder to detect timing differences.

💡
Every line of code takes time to execute, so even single-line differences can cause different execution times - and attempts at "pausing execution" until a timer runs out. That said, it's can also be incredibly difficult to measure these timing differences with such small variances. So having some protection is better than none, even if it's not perfect.

To make timing attacks easier, there is a specific technique called a Timeless Timing Attack that uses HTTP/2 multiplexing to send multiple requests at the same time, allowing you to easily compare the timing of specific requests without needing to account for slow connections, rate limiting, attempt limits, etc.

There is a great write-up about this vulnerability in Laravel by Jens Just Iversen from Ephort, which I recommend checking out if you’ve got time.

Not only did they investigate and report the issue, they also came up with a fix and introduced the new Illuminate\Support\Timebox class to Laravel in September 2022.

The class works by accepting a callback, inside which you perform your time-sensitive operation, and the minimum execution time in microseconds. If the callback takes less time to run execute than the minimum execution time, it waits for the remainder of the time. Therefore, it doesn't matter how many times the request is made, as long as the callback takes less time to execute than the minimum, the total execution time will be basically the same - defeating the timing attack! 🎉

Using it is as simple as this:

(new Timebox)
    ->call(function (Timebox $timebox) {
    
        // time-sensitive operation here
    
    }, $minimumExecutionTime);

This is how it’s used to protect Laravel login credentials:

protected function hasValidCredentials($user, $credentials)
{
    return $this->timebox
        ->call(function ($timebox) use ($user, $credentials) {
            $validated = ! is_null($user) 
                && $this->provider->validateCredentials($user, $credentials);

            if ($validated) {
                $timebox->returnEarly();

                $this->fireValidatedEvent($user);
            }

            return $validated;
        }, 200 * 1000);
    }

It’s not currently documented, but the class is very easy to understand so go check it out to learn more!

So if you’re implementing your own authentication system, or have other areas in your app where timing attacks are a risk, this is a great tool to add an extra layer of security into your app.

Thanks Jens and Ephort! 😁

🥷
Looking to dive deeper into Laravel security? Check out Practical Laravel Security, my hands-on security course that uses interactive hacking challenges to teach you about how vulnerabilities work, so you can avoid them in your own code!
🕵️
When was your last security audit or penetration test? Book in a Laravel Security Audit and Penetration Test today!