Anatomy of a WordPress Hack

So I’ll set the scene for you:

Disgruntled College of Charleston fan, home after witnessing a loss to Elon of all teams, wants to sit down, sip on some Gatorade, and work on his Facebook “25 Random Things” meme post because seven of his friends have now tagged him and he just wants to END IT (and terrorize additional people with said meme).

So, he sits down and begins writing his post, when he wants to refer to a post on his blog for some of the answers. He finds a strange white space in his layout that makes zero sense whatsoever. He goes and checks the source code…and OMG. Keywords. Lots and lots of keywords. Viagra, tablets, medicine — you name it, it was there. Site: Compromised.

Oh, and that guy? That was me.

I sprung into action and found that my site had been a reasonably popular target; I saw plenty of evidence of attempts on my site, including strange hits on the WordPress XML-RPC library and an attempt to get at my admin password that at least correlated with a possible time that the site was hit. I traced the IP and put a warning out on Twitter. Also, I implemented the .htaccess fixes on jazzychad’s site, reloaded WordPress, and removed legacy themes in case they were an attack vector (I had a plugin enabled that could do theme-switching on the fly). Continued investigation revealed a malicious user in my database which contained some extremely clever code to effectively hide it in the administration panel. I would never have noticed except for the fact that the administrator count now was reading “2.” I went into phpMyAdmin and did the appropriate database cleanup there.

However, something wasn’t right: Searching the logs did not indicate a successful logon to my admin panel. Bizarre. Could someone have been scrubbing the logs, too? I left nothing to chance and changed every password I could think of. I went through and carefully implemented some strategies for hardening WP as well. Thinking I’ve done all I could do, I moved along and felt reasonably safe.

A week later, I was hit again.

The damage the second time around wasn’t as bad, but it was befuddling, angering, and confusing. The theme, once again, was throwing up spam links. I reuploaded the theme and started taking another look at what was happening. Then, I remembered the one directory I didn’t check: wp-content. Sure enough, there were two files: wp-manager.php and cache.php that were problematic. I verified they were problems with the WordPress Exploit Scanner plug-in, which I now consider a must for any self-hosted WordPress installation. wp-manager.php was a file that appeared to be the vector to making the theme changes. cache.php was an R57shell, a common backdoor employed in site defacements. I pored over the logs that were available to me, and became convinced that there was a deeper issue than WordPress. Thus, I moved jaredwsmith.com to Media Temple (the shakeup I spoke of last week).

There’s nothing that hurts the geek-fu more than being compromised. However, there’s few things more soothing than knowing you aren’t the only one. And I’ve not been. Not by a longshot. The kicker? All these sites were on Dreamhost. The coincidence seems really weird, but I’m less convinced that these problems were all entirely WordPress’s fault.

I still don’t quite know how the site was compromised. Without access to the raw system logs, I will probably never know. However, this is a disturbing development and I hope with enough data a discovery can be made and this epidemic can be stopped. Regardless of where you host, keep an eye on your files, back up regularly, and be mindful to use strong passwords that are rotated on a frequent basis. Also, follow the official guide to hardening WordPress — there are some excellent techniques there. Site defacement is a very real problem; not only can it be embarrassing to look at, there’s also the real problem of people using site defacements to serve up malware (thankfully, this was NOT the case). There’s also the possibility of Google blacklisting because of spam keywords; depending on what you use your WordPress blog for, this could be a serious problem that could take months to recover from.

Being hit is bad enough, but it could have been a lot worse. Here’s hoping that moving to (mt) and a fresh WordPress 2.7.1 installation will lead to more secure times around these parts. Another silver lining for the Internet: I never finished my 25 Things Facebook post. :)

  • Wow, I’m glad I ran into this today. I have been working with a lot of WprdPress installations for people lately, and the information you’ve provided is going to be really helpful.

  • Wow, I’m glad I ran into this today. I have been working with a lot of WprdPress installations for people lately, and the information you’ve provided is going to be really helpful.

  • Happy to help, Rick — learn from my mistakes! :) After publishing, I found WordPress’s official hardening guide — some great nuggets in there as well.

  • Happy to help, Rick — learn from my mistakes! :) After publishing, I found WordPress’s official hardening guide — some great nuggets in there as well.

  • Patrick

    I’ve been trying to do an auto-install of WordPress 2.7.1, but I get a weird “fatal error” that stops the auto-install.

    I don’t think I’ve done a manual upgrade before, and I’m not thrilled with the thought. Tell me it’s pretty simple and shouldn’t be remotely intimidating to a Mac guy. Please?

  • Patrick

    I’ve been trying to do an auto-install of WordPress 2.7.1, but I get a weird “fatal error” that stops the auto-install.

    I don’t think I’ve done a manual upgrade before, and I’m not thrilled with the thought. Tell me it’s pretty simple and shouldn’t be remotely intimidating to a Mac guy. Please?

  • Actually, scratch that…I just got it to work.

    It turns out that you must DEACTIVATE the WordPress Automatic Upgrade plugin to be able to do a WordPress Automatic Upgrade.

    Because I work in television, that somehow makes perfect sense to me.

    At least I’m now at 2.7.1 now…and waiting for the next crisis.

  • Actually, scratch that…I just got it to work.

    It turns out that you must DEACTIVATE the WordPress Automatic Upgrade plugin to be able to do a WordPress Automatic Upgrade.

    Because I work in television, that somehow makes perfect sense to me.

    At least I’m now at 2.7.1 now…and waiting for the next crisis.

  • Yes, it’s funny how the Automatic Upgrade plugin throws automatic upgrades off all over the place. :) Welcome to 2.7.1!

  • Yes, it’s funny how the Automatic Upgrade plugin throws automatic upgrades off all over the place. :) Welcome to 2.7.1!