Blogs & Stories

SpiderLabs Blog

Attracting more than a half-million annual readers, this is the security community's go-to destination for technical breakdowns of the latest threats, critical vulnerability disclosures and cutting-edge research.

Jamming With WordPress Sessions

Let's talk about some targeted attacks where sessionmanagement can be targeted to side step multi factor authentication. I'll befocusing on WordPress, a popular website content management system, that alsojust happens to handle "sessions" in a unique way which makes this a far moreinteresting discussion.

At the time of writing, the current release: WordPress 3.5.1uses the described method to verify logged in status for accounts.

Here's an example WordPress "session", or authentication cookie:

Cookie name: wordpress_81aa6832caa89375bfc354face5f674e
Path: /wp-admin
Value: admin|1364335563|8b03a400e8e416c4eba7a63f6fd616d1

Once you have the equivalent cookie for a WordPress site(which for most WordPress sites is sent over HTTP, allowing it to be sniffedover an insecure wireless network at a coffee shop or conference) you would beable to go to the site's admin panel and already be logged in able do whateveryou want as that user. Oh, and that snazzy multi factor authentication pluginyou're using? It does nothing! Once you have a valid authentication cookie, WordPresswill let you access the site as an authenticated user, without needing to gothrough the multi-factor authentication process.

While I consider it pretty cool to side-step the MFA orauthentication steps, I dug a little more in to how WordPress manages these "sessions" and found out a bit more interesting facts. So, let's get back tothe authentication cookie, the first thing we want to do is track down is the name of thecookie, since it's pretty strange.

This turns out to be pretty straightforward; the cookienames are set in wp-includes/default-constants.php.

Screen Shot 2013-03-26 at 2.17.55 PM

Screen Shot 2013-03-26 at 2.18.57 PM

It's a constant that is set in the code and uses nothing atall, or the md5 of the value of $siteurl, which is the site's domain name, andinadvertently not hard to generate yourself.

Next let's look over the value.

Value: admin|1364335563|8b03a400e8e416c4eba7a63f6fd616d1

This is apparently three values separated by |'s. The "admin" username is obvious, and so is that Unix timestamp. That last value 8b03a400e8e416c4eba7a63f6fd616d1looks like the magic value that makes the whole system work. So let's see howit is set and how it is used.

Most of the action is in wp-includes/pluggable.php and I'llstart off with a snippet from wp_generate_auth_cookie() that handles settingthe cookie's value.

Screen Shot 2013-03-26 at 2.27.46 PM

Here you can see how $cookie is set, we can confirm theassumptions of the username, that timestamp is now evidently the session's expiration date, and now we see that the magic value isan md5 HMAC of user login andexpiration time as a string, using a secret $key value that was generated bywp_hash(). So, let's look into that wp_hash()

Screen Shot 2013-03-26 at 2.33.38 PM

Here wp_hash() returns a hash using hash_hmac() as well, but itmakes sure to use a salt generated by wp_salt() (it gets a little complicatedin the code (but it is all still in pluggable.php) but wp_salt() basicallyreturns the site's secret salt values.)

They provided the wp_hash() function the user login, only 4characters of the user's password hash, and the expiration date for the"session". wp_hash() returns the string from hash_hmac(), but also uses thewebsite's secret salt values to ensure a confidential string is generated.These salt values are key, as without them it would be trivial to generate yourown authentication token.

Now we know how WordPress sites generate a session cookie.Let's look into how they verify a session is valid, as that is where it getssurprising.

Instead of storing session information in a session tablestored on the server, they perform the same calculations on the cookie providedby the visitor to verify if it is valid. The site accepts the browser's cookievalues, then using the provided username + timestamp it calculates the tokenvalue using it's secret salts and sees if the generated token matches thesupplied token value.

We can look up the wp_validate_auth_cookie() function inpluggable.php to see for yourself. Spoiler alert: it looks basically the sameas the cookie generation function but with comparisons.

Screen Shot 2013-03-26 at 2.44.59 PM

You can see $hash is generated in the same way (re-using thesame code, and using values form the cookie provided by the browser) and thencompared against $hmac (which was pulled earlier from the cookie values) – ifthey do not match you get some "auth_cookie_bad_hash" action, if they do matchyou'll get "auth_cookie_valid".

The entire session management in WordPress hinges on 2secret values: The site's salts, and only 4 characters of the user's passwordhash. While this should prevent against brute force attacks, there are stillmultiple ways this method of authentication/session management can be a abusedby an attacker:

  1. Sessions hijacking (see: Firesheep)
  2. Lack of session management on the server
  3. Ability to create sessions without evidence lefton the site

This functionality has been in WordPress for a long time(since 2.x versions) and I'm not the first to talk about it. Independentresearchers have discussed it and there is a formal CVE regarding the concernof session hijacking with Wordpress sites.

  1. Just about a year ago, an independent researcherGennady Kovshenin (@soulseekah) wrote their findings about it in great detail http://codeseekah.com/2012/04/09/why-wordpress-authentication-unique-keys-and-salts-are-important/
  2. CVE-2012-5868 Session Replay attacks against WordPress(Reported December 2012)

At the time of writing this post, WordPress has yet toaddressed this concern. I have discussed it with their security team, and whiletheir response was respectful they informed me they have no immediate plans toenact a fix. In the meantime they recommend using HTTPS for your WordPresslogin page. (That is, presuming you have HTTPS setup on your WordPress site.)

Let us discuss those attacks:

I will skip going over session hijacking or replay attacks indepth (these have been covered elsewhere plenty of times.) To summarize: If youlog in to a WordPress powered website using an insecure connection, someoneelse on the network could sniff the cookies sent to your browser. They couldthen use the captured cookies to access the site. Programs like Firesheep havepopularized this type of attack.

The lack of session management on the server and the abilityto generate valid authentication cookies provides a unique scenario forattackers. They can generate "irrevocable" and undetectable valid sessioncookies. I say "irrevocable" because there are no documented ways to revokeyour site's authentication cookies. Knowing the code above, you may be able tosee how: In order to invalidate a WordPress authentication cookie you have onlytwo options. Change the user's password, or update the site's secret salts.Unfortunately, there are no easy ways to generate new secret salts in WordPresscore.

How about a hypothetical scenario to make this a little moreinteresting though? In this scenario we will say an attacker was able to gainaccess to, or guess the site's secret salt values. They would then be able to generatetheir own valid login cookies that expire at arbitrary times. There would be noevidence that the sessions had been generated and no way the site owner wouldknow these valid authentication cookies were created.

Here is a working proof of concept that will iterate throughthe site's users and generate valid authentication cookies for each user, and thatexpire in 2113.

Screen Shot 2013-03-27 at 7.45.29 AM

Of course, this is purely the hypothetical scenario wherethe attacker may have access to your site's secrets. However, this is true in apost-compromise scenario. If the attackers were able to break into your site,they could leave it untouched and just generate authentication cookies to allowthem access to your site later (even after you've patched the vulnerabilitythat allowed them access.) This is why any reputable article related to ahacked WordPress site will always inform you to change your site's secret saltsand passwords after a compromise. This step is required to invalidate anysession cookies attackers may have created for themselves.

To summarize:

  1. Even with Multi-Factor Authentication, the authenticationstep can be bypassed if session ID cookies are not protected.
  2. Storing session information on the server willallow you to monitor and disable sessions. This is extremely important in theevent of a breach.

I hope this post was informative and has made you more awareof the special bond between session management and authentication.