UPDATE: WordThumb has now been merged into TimThumb and has become TimThumb 2.0. Please head over to the TimThumb site now for updates and to get the code.
As I mentioned yesterday my WordPress blog was hacked. The security hole has been picked up by hacker news and from there, The Register, ZDNet, PCWorld, and Geek.com among others. The publicity will hopefully get Theme developers to update timthumb.php or switch to a different thumbnail generator.
I’ve been contacted with requests for detailed info, so I’m going to post the technical details of how my site was hacked along with the scripts that the hacker used to get in. This is targeted at a technical audience.
The server that served you this web page is the one that was hacked. It runs Ubuntu 10.10 with all security updates installed. It is a virtual server hosted by Linode.
I also run the latest version of WordPress.org.
My WordPress root directory was writable, but making it read only would not have prevented the hack.
Timthumb.php in it’s default configuration allows site visitors to load images from a predefined set of remote websites for resizing and serving. Timthumb offers a caching mechanism so that it doesn’t have to continually re-process images. The cache directory lives under the wordpress root and is accessible by visitors to the website.
The ability for a site visitor to load content from a remote website and to make the web server write that remote content to a web accessible directory is the cause of the vulnerability in timthumb.php.
To be clear, timthumb.php does not actually execute any remote malicious code that causes this vulnerability. This was a point of confusion among some commenters in my blog post yesterday. It simply gets a remote file and places it in a web accessible directory.
Timthumb only allows remote content from a small range of websites to be loaded remotely. In it’s default configuration these included Blogger, WordPress.com and other sites that are writeable by the general public.
Timthumb’s verification that remote content was only being loaded by these domains was also broken. You could for example load content from hackersiteblogspot.com or from blogspot.com.hackersite.com.
I’ve submitted a patch that fixes the pattern matching and removed all default public hosting sites from the allowed sites list. The developer has opted to keep a small list in which I’m not in favor of.
In my case the hacker uploaded a script to my cache directory which timthumb.php stores as “external_<md5 hash>.php”. He/she then accessed this script directly in my timthumb cache directory as something like https://markmaunder.com/wp-content/themes/Memoir/scripts/cache/external_md5hash.php
The script uploaded was Alucar shell which is base64 encoded and decodes when it executes. That makes it a little harder to find it using grep or similar tool. You can see the encoded version of Alucar here and the decoded version of Alucar here (without the username and password preamble at the top).
Here’s a screenshot of the UI:
This script which gives a web based shell access was then used to inject base64 code to one of my core wordpress files wp-blog-header.php which lives in the wordpress root directory. The file with injected code looked like this.
The decoded version of this base64 code is this. The code executes whenever a blog page is visited. It fetches a file from a URL and writes it to /tmp. Then it executes the php code that is contained in this file. In my case it simply echo’d some javascript code that would show ads. Here is the code contained in the file in /tmp.
Again, this file is periodically updated with new PHP code, so the attacker could have his way with my server until I found out about it. The code could be altered to instead become a spam system and work it’s way through a long list of spam emails.
The way I tracked this to conclusion was:
- Heard audio on my blog telling me I’d won something.
- Checked Chrome network tools and saw ad content loading and I don’t serve ads.
- Grepped wordpress source and themes for hostname I saw in ad. Nothing.
- Dumped mysql databases on server (all of them) and grepped for hostname. Nothing.
- Confusion reigns.
- Started working my way through nginx (which is my front end proxy to apache) and apache access and error logs.
- Spotted lines in apache error log like this: “[Mon Aug 01 11:09:12 2011] [error] [client 127.0.0.1] PHP Warning: file_get_contents(http://blogger.com.zoha.vn/db/load.php): failed to open stream: HTTP request failed! in /usr/local/markmaunder/wp-content/themes/Memoir/timthumb.php on line 675”
- Checked timthumb’s cache directory and found Alucar.
- Realized base64 encoding is why I didn’t find anything with grep.
- Regrepped wordpress source and database and found injection in wp-blog-header.php
- Decoded base64 stuff and played with Alucar
- Found tmp file in /tmp
- Cleaned everything and fixed permissions. Ran chkrootkit and other utils on machine to see if anything else was compromised. Changed passwords, etc.
Hi mark,
Great work, i added tim-thumb to my themes and checked it with themechecker [ http://wordpress.org/extend/plugins/theme-check/ ] , it shows a lot of warning, especialy the base 64 encoding, My testers are very much sharp in pointing it out, how should i remove those warnings or is it ok to go ahead.
Commented on December 1, 2011 at 5:46 am
Hi Mark, thx for the writeup! Quick question:
If I hosted my wordpress site (with the pre 2.0 timthumb script) in the public/wordpress/ directory (i.e. not the home directory) on a shared hosting server, do you know whether it’s possible that the hacker affected directories (such as injecting code into existing files or creating a new file) outside of the /wordpress/ directory? I.e. in the /public/ directory?
Commented on December 1, 2011 at 3:18 pm
Interesting that a few people have posted in the past few days. I had 2 sites hacked and reported to me by Google. However, In reading your information, it looks like it was hacked a while back. I thought I had cleaned it up, but it was the early stages of this hack’s appearance and not a lot of information was available.
I’m wondering if some hackers have recently unleashed some script intrusions that run malware and Google is notifying people of it?
Also, is it possible that the changed code will allow a hacker access to the hosting directory? I am considering wiping the entire directory and reinstalling to make sure it’s clean. I guess my question is: have there been any reports of further intrusions after we go through the clean up process you described?
Thanks!
Commented on December 3, 2011 at 10:13 am
I recently had 3 of my sites hacked. 2 of them WordPress and one Joomla. Same hack (Base64). I was able to clean the Joomla site, but both WordPress sites are jacked (for a lack of better terms). The IP addresses that were logged into my account actually belong to my web host, so I know that it wasn’t something that I uploaded. Since I pointed out that the IP address that they provided was theirs, they have not responded to any of my emails/tickets. Frustrated to say the least. (DREAMHOST)
Commented on March 3, 2012 at 9:54 am
If the moderator let it through, see my post above. Or just click http://forum.joomla.org/viewtopic.php?p=1889022#p1889022 for some insight.
Commented on March 15, 2012 at 3:06 pm
I’m following this tutorial for a test, locally, with XAMPP.
I can upload the image (test.php) but instead of creating the .php file in the “cache” of timthumb, is created only one image .PNG
How can it be that is created only a PNG (from gif + php code)? The exploit does not work that way because, obviously, you can not execute commands.
Commented on December 20, 2014 at 3:09 am