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.
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.
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! 😁