
Timing attacks are very difficult to pull off, but are possible nevertheless. However, it is quite easy to protect your Cake application against them, and as an aside – against incremental password crackers brute-forcing. This post shows you how.
What’s a timing attack?
A timing attack is when an attacker guesses your hashed password character by character, as opposed to using a dictionary or anything similar to try a brute force attack.
The way systems work is that your application hashes the password it receives from the user, and matches it to the hash it stores for this user in the users table.
This comparison stops at the first non-matching character. Therefore, it is possible to find your hashed value character by character, because the more correct characters you get – the longer the function takes to return. At least in theory.
What’s an incremental cracker brute force attack?
In an incremental crackin brute force attack, the attacker uses an incremental password cracker (e.g. John the Ripper) to feed your system a huge number of passwords – until it finds a good one.
While you may think that this takes time and effort – in reality these things rely on how responsive your web server is – so the faster your login code returns – the faster these tools will crack your user’s password (given a username, of course).
To this end, it makes sense to make your hashing algorithm as non-optimized as possible. This is nothing new, and has been out there for over a decade (look up ‘adaptive hashing’) but – most of these hashing algorithms, while they take their time – are at least consistent in the sense that they return their result consistently as well – therefore still rendering your system vulnerable to timing attacks.
The solution
The solution is only 2 lines added to the security.php file under cake/libs:
.
.
function hash($string, $type = null, $salt = false) {
$_this =& Security::getInstance();
//introduce a random sleep
$sleep = mt_rand(); //1
usleep(($sleep%1000000)*3); //2
//original code continues
if ($salt) {
.
.
The two lines above introduce a random wait time into your hash function.
line (1) generates a random number. The mt_rand function returns a number that can be quite large. Therefore, the usleep() method in line (2) uses its modulo 1,000,000 value, and multiplies it by 3, to introduce a sleep time of 0..almost 3 seconds. Since this is a pseudo-random number, it plays hide and seek with any timing-attack algorithm, but also delays incremental crackers enough to send them elsewhere.
The impact on your users should be minimal. They shouldn’t log on or log off more than once a session, and a mean time to wait of just over 1.5 seconds is not too bad in these scenarios.
Good luck!
Popularity: 3% [?]
Thanks for this tip! I found adding this to the Security hash function slowed down every page request. Instead I added the same 2 lines to password function in the Auth component, just before the call to Security::hash.