Blog

What is a Timing Attack

A timing attack is a crytography issue where a hacker attempts to use the difference in processing time between two actions to gain information. Individually, the information gained is the amount time it took to run the process with a particular set of input. Performed once, the processing time is insignificant, however when performed in a series, the hacker can adjust the input (ie password for a particular username) and use the increase or decrease in time to create a security hole by drastically reducing the potential.

Normally, when software compares two strings it starts with the first character of each string and determines if the characters are the same. If the first characters are the same, it moves to the second characters and tests them. This process continues until two characters are found to be different or one string runs out of characters. Conceptually, if it took 1 second to compare two 1000 character strings and it took 1 millisecond to determine the first character, it would be useful to know that it took 54 milliseconds to compare two strings. The implication is the 54th character is the first character different between the two strings.

In a cryptographic sense, the hack would only know one of the two strings, the password inputted. If the password on the server is properly secured and hashed in the database, then every failed password will take roughly the same process through the system, with the comparison between the hashed password and the hashed version of the input password being the only real difference. Systematically changing the input password while comparing it to response times could allow the hacker to break the password in a practical amount of time by reducing the password combinations exponentially as each character is determined.

Fixes

Some programming languages and operating systems have special functions for comparing password hashes. Outside of these special functions, there three ways to disrupt a timing attack.

1) Rehash the hashes

By hashing the hashes and comparing the doubly hashed values, you are performing the comparison of two "strong password" style strings rather than the potentially "weak password" style strings. This shift drastically increases the number of potential possibilities, increasing the time it takes to perform the attack, potentially to impractical levels.

The problem with this approach is you are reducing the usefulness of the leaked information, thought not completely eliminating it. Depending on the computing power available to the hacker, theoretically this approach can still be overcome.

2) Inject a random delay

Inserting a random microsecond delay in the processing would distort the leaked information, making the information insignificant.

The problem with this approach is the speed of your own processing. This approach is dependent on the system having a microsecond processing time. If, for example, the comparison operator took tens of microseconds to process and you were adding between 0-9 microseconds, you have only distorted, and not hide, the leaked information. This means you would have to appropriately adjust the random factor per the processing speed of the current system or place the range in such a way that you would be wasting resources (ie making the script run tremendously longer than necessary).

3) Manually compare the entire strings

Because the basic string comparison operator works on an array basis, manually running through every character in the string (via a for loop and direct access to each character) removes the time difference created by the simple string comparison operator. Once a different character is identified, a bit flag is set and the comparison continues until every character is compared.

This is the preferred method and the basis for any of the special functions for password comparison.

In PHP this function would be roughly

  • function compare_hashes($hash1, $hash2) {
  •     if( !is_string($hash1)
  •             || !is_string($hash2)
  •             || empty($hash1)
  •             || empty($hash2)
  •            ) {
  •         return FALSE;
  •     }
  •  
  •     if( ($len = strlen($hash1)) != strlen($hash2) {
  •         return FALSE;
  •     }
  •  
  •     for( $i = 0; $i < $len; $i++) {
  •         $flag |= ord($hash1[$i]) ^ ord($hash2[$i]);
  •     }
  •     return (!$flag);
  •  }

 

Other Notes

In a practical sense, timing attacks are less of an issue than a copy of the password table from the database being leaked. Normal methods of blocking brute force attacks defeat most of the risks associated with Timing Attacks, but the ease of the fix is such that implementing a proper hash comparison is worth it.