On the evening of March 27th, I discovered several WordPress websites I maintain were hacked. Most notably, southwestraleigh.com. My personal site, hibbets.net, was also compromised in the early hours of the morning.
As I started checking all the client websites I maintain for Red Waves, I found it was only WordPress sites that were compromised. It was easy to see, because the hacker took over the home page of the sites with a political message.
I believe the compromise exposed a vulnerability in WordPress sites that were not updated to 3.1. I admit, I was behind in upgrading these sites to the latest version. If you remember only one thing from this post, remember to maintain your site updates.
I was curious how the hacker got in and what they did. Before we go down that path, it’s important to note the the steps I took to restore my sites.
Restoring hacked sites
- I contacted my hosting provider to make them aware of the situation
- I requested the hosting provider restore my website files so that traffic coming to the site would not see the compromised messages
- I downloaded certain information like log files, error messages, and databases back-ups
- After an exhaustive discovery (below), I requested full restoration of web and database files for each site from a back-up made previous to the compromise
- When each site was restored, I changed the passwords and upgraded the WordPress installations (and plug-ins) to the most recent updates
The Steps the Hacker Took
Here is how they discovered the site. They ran a search on “WordPress” and the IP address of the server. So it appears that this was a random, spidered attack, not a targeted one to me or other sites.
41.226.160.125 – – [27/Mar/2011:18:42:27 -0500] “GET /2011/03/1st-annual-state-pattys-day-scavenger-hunt/ HTTP/1.1” 200 44559 “http://www.bing.com/search?q=ip%3a69.175.84.146+wordpress&go=&qs=n&sk=&sc=8-20&first=21&FORM=PERE1” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16”
I noticed other sites on the same server were compromised by Ahmdosa Hacker.
It appears they logged in with no issues, which is very strange to me. To be honest, I find it very hard to believe that they had passwords for all these WordPress sites. They probably exploited a known security vulnerability in WordPress, which is why you should always upgrade. Here is the access line from where they logged in:
41.226.160.125 – – [27/Mar/2011:18:44:12 -0500] “POST /wp-login.php HTTP/1.1” 302 – “http://…/wp-login.php?redirect_to=http%3A%2F%2Fsouthwestraleigh.com%2Fwp-admin%2F&reauth=1” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16”
Then, they used the theme editor to break WordPress and allow them to upload a malicious script called product-MF.php, which seems to be a newer variant of a shell like hack called NeT-Own3r, according to a security expert I consulted.
41.226.160.125 – – [27/Mar/2011:18:44:43 -0500] “POST /wp-admin/theme-editor.php HTTP/1.1” 302 – “http://…/wp-admin/theme-editor.php?file=/themes/twentyten/functions.php&theme=Twenty+Ten&dir=theme” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16”
41.226.160.125 – – [27/Mar/2011:18:44:58 -0500] “POST /wp-admin/theme-editor.php HTTP/1.1” 200 636 “http://…/wp-admin/theme-editor.php?file=/home/public_html/wp-content/themes/twentyten/functions.php&theme=Twenty+Ten&a=te&scrollto=0” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16”
41.226.160.125 – – [27/Mar/2011:18:45:00 -0500] “GET /wp-admin/product-MF.php HTTP/1.1″ 200 54223 “-” “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.151 Safari/534.16”
The product-MF script seems to provide the hacker with shell access, has an IRC bot associated with it, and can turn off PHP safe mode and Apache’s mod security. This is powerful to a hacker who needs to gain access to a system.
When I reviewed the error logs, you could see the function.php script in the WordPress theme directory showing some errors. When I looked at the actual file, it had a file size of 0.
PHP Warning: copy() [<a href=’function.copy’>function.copy</a>]: Filename cannot be empty in … [the WordPress theme directory]
PHP Warning: Cannot modify header information – headers already sent by (output started at [the WordPress theme directory]) in … /wp-admin/theme-editor.php on line 99
I don’t know the extent of what was changed, but I do know they modified the passwords for any WordPress user who was an admin. They were also able to modify the index.php files or configure a redirect for any sites not using WordPress in the root directory.
Most people are embarrassed to get hacked. I’m no different. In all my years on the web, this is the first time happening to me. I’m sharing my story to help others out. I wish all this energy doing bad things on the web could be used to solve some of real problems instead of creating headaches. Don’t you?
Feel free to contribute additional details, resources, or stories in the comments.
After my last WordPress hacking episode, I decided to really lock down my server. I have a cron job which periodically changes the file ownership in my web directory to something other than Apache. That way, the odds of a hacker uploading a malicious script are practically eliminated.
Now, when I want to upload a photo or make other changes, I first run a script from the command line which resets the directory ownership of the upload dir to apache. Then I upload my image and the cron script will soon change the permissions back to something that WordPress can’t write. This little trick has worked wonders.
Also, I’ve created a hefty .htaccess file which blocks libwww-perl agents, among other things. Hit me up if you’d like a copy of that.
I do a lot of WordPress work for clients and this has definitely spooked me. I’m not likely to go the advanced route that Mark has, but I’d be interested in hearing about any solutions that are as easy as Mark’s extra .htaccess rules (btw – send ’em to me Mark 🙂
Working on WP security today, I found that the 1-click install for WP on my host doesn’t value the authentication keys stored in wp-config.php
http://codex.wordpress.org/Editing_wp-config.php#Security_Keys
I didn’t even realize these were in wp-config (the 1-click has made me lazy).
Scott, could you explain the security implications of the authentication keys being listed in wp-config.php? Is there some easy remedy? I assume they can’t simply be deleted…
Thanks to you and Shibby for revealing this flaw and the cure!
Tom
I don’t know about the auth keys in the wp-config, but I went into my database and cleared out the user keys for each user in case those were copied.
Jason
The keys/salts in your wpconfig will increase the security of the cookies of logged-in users. You don’t need to clear the user keys if you change the keys in wpconfig. Changing them will force the user to re-login. If you look in wpconfig, they even give you (via a comment) a URL for the API that will generate strong auth keys.
I’ve been chasing problems this past week on my own websites and after reading your article here, I believe I may be dealing with a hack that utilizes the same security hole to get into the system, but isn’t using “product-mf.php”
In my case, the hack seems to be inserting a block of code into every “index.*” file it can find. Depending on if the infected file is HTML or PHP, the inserted code is either a simple iframe tag or a somewhat more sopisticated bit of PHP code which ultimately inserts a similar iframe tag.
Upon figuring out I’d been hacked, the first thing i did was re-upload clean versions of the infected files. Then I noticed they were getting infected AGAIN just a few minutes later. And then I saw that other files were being infected too.
I noticed that setting a file to read-only status after uploading it would prevent reinfection, so I created a PHP page which scanned files for the infection, REMOVED it if found, set the file to read-only, and then recorded the specifics in a database so I could track everything.
This accomplished two things… first it ensured that a hacked file got fixed ASAP, second, it helped me pinpoint the exact moment when a file got hacked, so I had a timecode reference when looking at the server logs. That’s what led me to find several places where there was something like what you listed in your article:
http://…/wp-login.php?redirect_to=http%3A%2F%2F…%2Fwp-admin%2F&reauth=1
I did NOT find any references to “theme-editor.php” or “product-mf.php” so this is clearly not the same exact problem as what you experienced. However, they may be similar enough that the measures you undertook to fix things may also apply.
I’ve been working on fixing things the right way. I changed the admin login passwords. I upgraded my sites to the new 3.1.4 release. I deleted unnecessary plugins and upgraded others. I’ve added a couple of recommended security plugins that do things like beef up the .htaccess file. And I’ve changed my auth keys in wp-config.php.
Upgrading WordPress the way I did — deleting the old files & folders first, then copying over the new stuff, should have zapped any file equivalent to “product-mf.php” along the way.
At this point, it’s been over 48 hours since the last hack occurred, so I’m reasonably confident I’ve closed the hole. However, I am not entirely sure what the hole actually was, so I’m therefore concerned that the original infection vector may still be present. Maybe I’ve just made it harder for it to actually screw with anything.
And that FINALLY gets us to the question(s) I have for you.
How did *YOU* fix it? Is the security hole that let them into the system in the first place now fixed, or does even the latest 3.1.4 version of WP still have this problem?
Hi Mike,
I was unable to pinpoint the exact security hole, assuming that upgrading WordPress did the trick. I was thinking that if it was fixed, it was very vague in the change log when I reviewed the difference in versions. Unfortunately, I’m not 100% certain that the it’s fixed, but like you, things have been running smoothly for a while.
Keeping my fingers crossed!
Jason
Jason, I was really quite annoyed myself at how few details regarding what was changed were included in the the WordPress site’s changelog. I can only guess that they’re concerned that saying more would lead to more people exploiting the problem on sites that haven’t upgraded yet.