Timing Attacks in Web Applications
When code is executed by a machine it takes some time to do so. Execution time ranges from nanoseconds to months and years and even more (think bruteforcing). Web applications construct output producing, in most cases, very short delays (think the time it takes to show Google search results after typing in the query). Depending on what output is request, how it is requested and what the input is web applications can vary their execution time.
In this article we’re going to exploit some of the open-source content management systems available using delays in its execution under differing conditions to evoke distinct differences in execution time, which allow us, as attackers, to make some useful conclusions.
WordPress
You should know what WordPress is. It’s only the most popular content management system at the moment, and the slickest one, too.
wp-includes/user.php is the code that we shall be attempting to exploit. This code handles user authentication in WordPress.
Take your time to go through the function code. You can immediately see early return conditions. When username is not found and error is returned. If a username is existent – the password is hashed and checked against the valid password hash for the user.
So, hashing the input password is work that does not happen if a username does not exist. And hashing is an expensive operation relative to everything else, so potentially a difference in time should be noticed. Armed with cURL we do:
time curl --data "log=noexist&pwd=asdf&wp-submit=Log In" http://wordpress.lo/wp-login.php --silent > /dev/null
real 0m0.599s user 0m0.012s sys 0m0.000s
time curl --data "log=admin&pwd=asdf&wp-submit=Log In" http://wordpress.lo/wp-login.php --silent > /dev/null
real 0m0.566s user 0m0.000s sys 0m0.012s
Having done this a couple of times you’ll notice no difference. Due to fluctuating network latency and other factors the results are in no way conclusive. So let’s prepare a larger password to hash to make WordPress huff and puff a bit.
echo -n "log=noexist&pwd=" > payload && printf "%s" {1..100000} >> payload && echo -n "&wp-submit=Log In" >> payload
~500 kilos worth of password characters to hash, eek.
time curl --data @payload http://wordpress.lo/wp-login.php --silent > /dev/null
real 0m0.511s user 0m0.012s sys 0m0.032s
echo -n "log=admin&pwd=" > payload && printf "%s" {1..100000} >> payload && echo -n "&wp-submit=Log In" >> payload
time curl --data @payload http://wordpress.lo/wp-login.php --silent > /dev/null
real 0m29.803s user 0m0.012s sys 0m0.036s
See? This is, of course, very far from useful in the context of WordPress, since WordPress is kind enough to give out different error messages depending on whether a user exists or not.
ERROR: The password you entered for the username admin is incorrect. vs. ERROR: Invalid username.
The same cannot be said for other applications.
Drupal
Authentication in Drupal is handled by the user module, found in modules/user/user.module. Take a peek at the user_login_authenticate_validate
function. See the branch that allows some extra work? if ($account) { ...
.
The principal is the same. However, short passwords so make Drupal work noticeably enough.
time curl --data "name=noexist&pass=123&op=Log in&form_id=user_login" http://sandbox.lo/drupal-7.12/?q=user --silent > /dev/null
real 0m0.593s user 0m0.012s sys 0m0.028s
time curl --data "name=admin&pass=not_real&op=Log in&form_id=user_login" http://sandbox.lo/drupal-7.12/?q=user --silent > /dev/null
real 0m1.181s user 0m0.012s sys 0m0.028s
So no need to assemble large payloads. Thanks, Drupal.
Joomla!
The more convoluted Joomla authentication routine is stowed away in plugins/authentication/joomla/joomla.php, onUserAuthenticate
. Take a moment to look at it. The scenario is completely the same, if ($result) { ...
does extra work if user exists and $testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt);
will do some work if user exists, theoretically.
The difficulty here is that by default Joomla uses md5 hashing, which is relatively lightweight and very fast. Joomla doesn’t really mind hashing 10MB password payloads and is not susceptible to such attacks in md5 mode. Yet, once it’s in any of the other available hashing modes timing attacks to check username validity are possible.
Conclusion
Do you know of any other popular web applications that are predisposed to any form of timing attacks?