Zero Day Vulnerability in many WordPress Themes

Big News [April 24th, 2012]: I’ve launched Wordfence to permanently fix your WordPress site’s security issues. Read this now.

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.

Update 4: I’ve also added the ability to screenshot websites to WordThumb.

Update 3: I have forked timthumb.php into a new secure thumbnailer project called WordThumb. It’s a complete rewrite of timthumb and is fully backwards compatible. The only code that is recognizable is the image processing code. All file handling has been rewritten from scratch and I’ve fixed quite a few bugs. The project is now live on Google Code and version 1.0 of WordThumb is up for download. You can read more details about the changes in this blog entry about WordThumb.

Update 2: After evaluating timthumb.php I’ve decided the best solution to the security problem is to fork the project and do a line-by-line rewrite. I started work on this a day ago and it will be published on this blog later today. (This was posted on Wednesday at 11am Pacific Time). Please check my blog’s home page this evening (in about 8 hours) and it should be done.

Update: Ben, the developer of timthumb has been in contact and is working on a fix. His own site was hacked Friday using the same method. I’ve submitted a tiny patch and if you’re a solid PHP hacker it’d be great if you could eyeball the code with us and submit a patch (really easy to do on Google code) if you spot any other opportunities for cleanup (there are many). Given enough eyeballs… you know the quote.

The Exec summary: An image resizing utility called timthumb.php is widely used by many WordPress themes. Google shows over 39 million results for the script name. If your WordPress theme is bundled with an unmodified timthumb.php as many commercial and free themes are, then you should immediately either remove it or edit it and set the $allowedSites array to be empty. The utility only does a partial match on hostnames allowing hackers to upload and execute arbitrary PHP code in your timthumb cache directory. I haven’t audited the rest of the code, so this may or may not fix all vulnerabilities. Also recursively grep your WordPress directory and subdirs for the base64_decode function and look out for long encoded strings to check if you’ve been compromised.

How to fix:
Update: As per several requests I’m posting hopefully easy to use instructions on how to fix this. This is for the latest version of timthumb.php version 1.33 available here. Check your version because there are many much older versions floating around.

NOTE: timthumb.php is inherently insecure because it relies on being able to write files into a directory that is accessible by people visiting your website. That’s never a good idea. So if you want to be truly secure, just delete the file using “rm timthumb.php” and make sure it didn’t break anything in the theme you’re using.  If you still want to use it but want to be a bit more secure, you can follow the instructions below.

This will disable timthumb.php’s ability to load images from external sites, but most bloggers only use timthumb.php for resizing local images:

  1. SSH into your web server. You can use “putty” if you use windows and you’ll need to know your username and password.
  2. cd into your wordpress installation directory. That is going to vary according to which host you’re using or how you’ve installed it.
  3. You need to find every copy of timthumb.php on your system. Use the following command without double quotes: ” find . -name ‘timthumb.php’ “
  4. It will show you a list of where timthumb.php is located. You may want to repeat this command using “thumb.php” as some users have reported that’s what it’s called on their systems.
  5. Edit timthumb.php using a text editor like pico, nano or (if you know what you’re doing) vim. You would type (without double quotes) ” nano directory/that/tim/thumb/is/in/timthumb.php ” for example.
  6. Go down to line 27 where it starts $allowedSites = array (
  7. Change it to remove all the sites listed like “blogger.com” and “flickr.com”. Once you’re done the line should look like this from $allowedSites to the semi-colon:
  8. $allowedSites = array();
  9. Note the empty parentheses.
  10. The next line should be blank and the following line will probably say “STOP MODIFYING HERE”
  11. That’s it. Save the file and you’re done.

Full post:

Earlier today this blog was hacked. I found out because I loaded a page on my blog and my blog spoke to me. It said “Congratulations, you’re a winner”.

After a brief WTF? I loaded up the dev tools in Chrome and checked what network requests were going out. Ad content was loading and I don’t run ads on my blog. For some reason the content was hidden, perhaps someone gets paid per impression.

I found the hostname the ads were loading from and grepped the WordPress code for the hostname and nothing turned up. Next I dumped the database  - in fact all mysql databases on the server and grepped for the ad hostname and still nothing.

Eventually I found it. The hacker had done an eval(base64_decode(‘…long base64 encoded string’)) in one of WordPress PHP files. My bad for allowing that file to be writeable by the web server. Read on, because even if you set your file permissions correctly on the WordPress php files, you may still be vulnerable.

But what I really wanted to know was how the hell he wrote to a file on my machine.

I checked my nginx and apache access and error logs and eventually found a few PHP errors in the apache log that clued me in.

Turns out the theme I’m using, Memoir, which I bought for $30 from ElegantThemes.com uses a library called timthumb.php. timthumb.php uses a cache directory which lives under wp-content and it writes to that directory when it fetches an image and resizes it.

If you can figure out a way to get timthumb to fetch a php file and put it in that directory, you’re in.

The default configuration of timthumb.php which many themes use allow files to be remotely loaded and resized from the following domains:

$allowedSites = array (
	'flickr.com',
	'picasa.com',
	'blogger.com',
	'wordpress.com',
	'img.youtube.com',
	'upload.wikimedia.org',
	'photobucket.com',
);

The problem is the way the developer checks which domain he’s fetching from. He uses the PHP strpos function and if the domain string appears anywhere in the hostname, he’ll allow that file to be fetched.

So if you create a file on a web server like so: http://blogger.com.somebadhackersite.com/badscript.php and tell timthumb.php to fetch it, it merrily fetches the file and puts it in the cache directory ready for execution.

[Note: I'm 99% sure this will work on most webserver configurations because the cache directory that timthumb uses is a subdirectory of directories that are allowed to execute files with a .php extension. So unless you explicitly tell your server to not execute .php files in the cache directory, it'll execute them. ]

Then you just access the file in the cache directory on the target site using your web browser and whatever code came from http://blogger.com.somebadhackersite.com/badscript.php will get executed by the web server.

In my case, this is what the hacker saw when he accessed my site:

It’s called Alucar shell and it’s a php file that contains one massive base64 encoded string that gets decoded and evalled. It’s encoded in an attempt to hide itself.

When you first hit the script it presents you with a login page and once you’re signed in you see the screenshot above. It works quite well actually. Even if the rest of your filesystem is secure, whoever is using it can dump read-only files like /etc/passwd to get a list of user accounts, config files which may contain passwords, etc..etc..

The current version of timthumb has this issue. Since it’s already in the wild and I just got hacked by it, I figure it’s ok to release the vulnerability to the general public.

To check if you have been hacked do the following:

  1. Sign into your server using ssh
  2. cd to your wordpress installation directory
  3. run “grep -r base64_decode *”
  4. You should see a few occurences but if any of them have a long encoded string between the parentheses, then you’re probably hacked.
The hacker used base64_decode in the file uploaded to the timthumb.php cache directory as well as where he injected code in my blog.
Also check your /tmp/ directory and if you have any suspicious files there like xwf.txt or any other .txt files, look at them in a text editor.
How to (possibly) fix this:
  1. Go into your theme directory and figure out where timthumb.php is.
  2. You might try “find /your/wordpress/dir/wp-content/themes/YourTheme/ -name “timthumb.php””
  3. Edit timthumb and remove the list of external websites that content is allowed to be loaded from.
  4. I have not audited the rest of the code, so this may or may not make it secure.
  5. The developer really needs to use a regular expression to check the external hostnames images can be loaded from.
I would also recommend that if you’re a theme developer using timthumb.php, you check to see how it’s configured and try to load a php file from blogger.com.yoursite.com to see if you’re vulnerable.

154 thoughts on “Zero Day Vulnerability in many WordPress Themes

  1. I think that what you posted made a lot of sense.
    However, what about this? what if you typed a catchier
    post title? I am not suggesting your information isn’t good, however suppose
    you added a headline to possibly grab people’s attention?
    I mean Zero Day Vulnerability in many WordPress Themes | mmmm is kinda vanilla.
    You might look at Yahoo’s home page and note how they create article headlines to grab viewers to open the links.
    You might add a related video or a related picture
    or two to get people interested about what you’ve got to say.
    Just my opinion, it might bring your posts a little livelier.

  2. There are several conventional mmorpgs all-around, and possibly there’re thinking about sturdy. And also the certain sound resistence vs . online-only. Since it?s having much more widespread, is just not gonna advocate it will get preceding the entire small business plus virtually all free online games will probably be online-only.

  3. Hello there, I discovered your website via Google at
    the same time as looking for a related topic, your web site got here up, it seems great.
    I have bookmarked it in my google bookmarks.
    Hello there, simply changed into aware of your weblog thru Google, and found that it is truly informative.
    I am gonna watch out for brussels. I’ll be grateful in the
    event you continue this in future. Lots of folks will likely be benefited from your writing.

    Cheers!

  4. After I originally left a comment I appear to have clicked the -Notify me when new
    comments are added- checkbox and now every time a comment is
    added I get four emails with the same comment.
    Perhaps there is a way you are able to remove me from that service?
    Appreciate it!

  5. Hi! I’ve been reading your website for some time now and finally got the bravery to go ahead and give you a shout out from Humble Texas!
    Just wanted to tell you keep up the excellent job!

  6. Hi Everyone,

    My site was hacked for the first time and has really put my head spinning, my host indicated it was the timthumb plugin and they helped me to correct it. I use the WP Twenty Eleven Theme and when I google it I find this was not used for the theme?

    Anyway I’m trying to follow along here to double check but I’m afraid I’m lacking the knowledge, I also dont have ssh access can I check for these files through Dreamweaver? I noticed a reply earlier suggesting files to look for but dont see them so I guess its a good thing.

    I dont really trust the customer service at my host, they seem to not be at all concerned they simply said they removed the timthumb files and told me to change my passwords.

    Then I read about all these other backdoors and files and am a bit lost by it all trying to figure out if my site is actually OK or just a timebomb waiting for the next hack.

    Would anyone be willing to provide a few step by steps on what us Tech challenged people can do to help secure our WP sites in the future.

    Thanks

  7. Ok so I downloaded the latest Timthumb and I uploaded it via CuteFTP to the exact location and I overwrited the file.

    Now when I go to let’s say ALL POSTS on WP it loads then not showing anything. How do I fix this?

    I’m sure it’s simple but too bad I’m not a dev to know it :(

    Please help,
    Much appreciated
    Ali

  8. Well, I had two sites on Google’s blacklist, but I cleaned up the sites and will now update the php to the latest version so that I don’t have my sites again on the blacklist. Google removes from the blacklist within 24 hours if you contact them through Webmaster Central.

    Thank you for all you work on updating the file to make it safer.

  9. FYI:

    I just had a massive attack looking for timthumb – the bot being used pinged my site 134 times looking for timthumb or thumb.php in various themes. It looked for a scripts subdirectory and a tools subdirectory then it looked in the specific theme base directory.

    I use WordPress Firewall that is suppose to stop those kinds of hacks but since my install of timthumb didn’t match their script it didn’t succeed anyway. But the Firewall at least lets me know when an attack happens.

    This is what one of the offending links were:

    wp-content/themes/Nova/scripts/timthumb.php?src=/g0../0d1.gif

    The IPs involved include:

    66.147.244.188
    182.50.142.160

    Just FYI on what to look for

    • @Doug – I also use WP Firewall 2 Plug in and had the same exact thing happen yesterday. Tons of blocked attempts to try to get into a timthumb script on a theme I do not have. They seemed to be trying all the popular themes in case I was using one.

  10. Hi,

    I have applied the timthumb update and removed any hacked files that have long occurrences of base64_decode in them.

    I’ve also changed ftp passwords.

    Is there any chance that they have access to the database?

    How do we know when we have removed all trace of the hackers?

    • Hi Alex,

      This is tough and it’s hard to make gaurantees. To give you some perspective, if they managed to get a shell and then managed to get root on your machine, they may have installed a kernel module rootkit which completely hides their presence. It patches programs like ‘ls’ or ‘ps’ so you can’t see files or processes belonging to them.

      The majority of hacks I’ve helped fix in the last few weeks did not have this level of compromise. They simply used timthumb to write to core wordpress files. In the worst cases, the code would auto-update itself from a hacker’s URL and inject new spam links periodically.

      If your database server is public it’s likely they have access because they could have read your wp-config.php file and gotten the username/passwords there which are stored in plaintext.

      So change your DB password to be safe.

      Best of luck!!

      • Thank you for getting back to me so quickly!

        Yep what I have discovered is that some core WordPress files had been written to. I have replaced those files.

        I guess now it is a case of waiting to see if that has killed it.

        • That’s a good question. You need to know a bit of linux to do this. You need to find your database hostname in your wp-config.php file, find the hostname, username and password and then try to connect to it from a remote machine or from home. You’ll need to fire up a mysql client, enter the details and try to connect. Hope that’s not too technical.

  11. My site is blocked as well, almost for 2/3 days now. I had the feeling I’m among one of the first that has been blocked.

    http://donotargue.com

    Thanks to your article about the grep – base I asked my host to run those commands on my whole public_html folder so all my domains have been scanned. I have fixed all the hacks/altered code/files etc etc.

    How long will it take Google to unblock me, they had seen the l10n.js file as mall-ware infection (and it was and has been fixed) this is costing me allot of traffic and users.

  12. I have gone through a rough week with this issue. I updated my timbthumb 3 days ago and then yesterday couldn’t view my blog because there was a pluggalble.php header issue. My host gave me a temporary fix but recommended I delete EVERYTHING from host and start again. I have a TON of stuff including lots of video and audio files. I don’t know where to start … do I have to delete it all? Can I browse through the directories and look for SOMETHING? Thanks for your feedback.

  13. Hello Mark, I read about this zero days and since i am a developer, and a junior web security consultant, i have come to experience that, even your updated codes doesn’t solve the problem. i have tested it all. but anybody is still able to access the files and directories. So i decided to bring a temporary solution for it, i have simply created a “index.html” in the directory wherever timthump.php is residing, also there , where the timthump.php is saving the created image file says “cache” directory. Though it still won’t solve the real problem but atleast it would stop the direct viewing of files on the ftp server.

    I would love it, if you can enlighten me a little more.

    thanks,
    Rohit

    • Hi Rohit – Marks fix was a temporary one. Please update TimThumb to the latest version – that has considerably more security improvements than Mark suggested above.

      • Hello Ben, Yeah, I have updated the file already. But trust me , as a hacker perspective, it didn’t change anything. Thats why i had to put a temporary index file to hide the files.

        Hope Mark will come with a better solution soon next time.

        • If you had updated the files then you would have seen that it automatically creates an index.html file so that the directory does not get listed. You would also have seen that it adds a .txt extension and prepends some php in every cache file so that they can’t be executed.

          • Thanks for your quick response, Yes i had changed back to my early version of timthumb coz with timthumb 2.8 , my server was responding slowly. I had a little chat with my server care today and now its solved. now its updated to 2.8 .

  14. Hi Mark-
    Thank you for this write up. I’m a writer/photog, not a developer of any sort, but I was still able to clumsily follow my way thru.
    As of this morning my site was blocked by Google. Unfortunately, the timthumb.php I had on that site is a very old one without the ‘allowed’ sites line. So it appears they got ‘in’ somewhere else. Google webmaster Tools says it’s this file: wp-includes/js/l10n.js
    BUT–the file now looks totally normal per the code Google says it should have. Any suggestions would be greatly appreciated.
    Thanks!
    Lisa

    • Hi Lisa,

      It looks like this file:

      http://www.llworldtour.com/wp-includes/js/l10n.js?ver=20101110

      Is clean right now. So I think it’s going to take a few days (weeks?) for google to unblock your site. You’re the second site that’s reported being blocked by Google in 12 hours, so it looks like they’re busy taking action right now.

      I’m about to post a blog entry on this. Can you do me a favor and send me a screenshot of webmaster tools telling you it’s the l10n.js file? I’d like to include it in the blog entry.

      I’ll reach out to a few SEO friends and try to put together a todo list to get unblocked for you.

      Mark.

      • Hi Mark-
        Thanks for the very quick response. So…if I didn’t clean up the file…who did or why is it clean now?
        I also use a WordPress firewall plug-in..so how do these people get into my files. I’d love a bit about tools to put in place that keep wordpress sites/servers more secure. I am currently on Blue Host.
        I will send the screen shot right now.
        Thanks again. I appreciate this helpful community when I have no idea where to turn.
        Lisa

        • Sorry I misunderstood, It thought you cleaned it. That’s very odd. I’ll investigate further – I’ll take a look at the google malware list and see if I can figure it out. Send me that screenshot!

  15. Ben: Apology NOT accepted, and yes: somebody HAS “has anything too bad happen to their sites because of (your) error.”

    I should never have trusted a third party. My site is a mess; Google has flagged it as an “attack site,” and my ‘net cred is down the crapper.

    Granted, it’s as much my fault as yours for having been so blind with my trust. I can’t follow all these quick-and-dirty patches that may or may not work. From here on out, I trust NO ONE.

    Thanks for nothing, Ben — nothing but eight years of work down the toilet.

    • Oh my. Not sure I want to take sides on this one. I see lavenderliberal.com has been flagged as malware because it contains links or code from news.lavenderliberal.com, also your site and I’m assuming the one that was hacked. I see you now have a message up on the news site.

      This is very very unfortunate and the first example where I’ve seen a compromised WordPress site get flagged by Google. It’s basically a worst case scenario.

      If you don’t mind I’d like to blog about this. Could you contact me at mmaunder at gmail dot com for an interview? Getting the story out may help prevent this from happening to others.

      Again, really sorry to hear about this.

      • You’re right. I apologize to everyone. There’s no excuse except that I’m upset beyond words. I’m a fanatic about keeping my site safe and doing everything above-board, and one tiny line of code out of my control brings it all crashing down. Again, I’m sorry for being so harsh — I’m just deeply depressed over my dead site (I’m not the whiz-bang geek who can fix it by myself, so rather than put others at risk, I killed the blog), and I’m afraid to take such a risk again. Hackers are smarter than I am — what will they do next time? Rhetorical question.

        • Hi: If it makes you feel better I have all 14 of my Blogs Hacked by the same Turkish Hacker Activist with a Message,
          a bad attitude and too much time on his hands. I traced the
          Hacker back to his favorite forum an quickly joined. I found out that there is a million ways into WordPress sites. Mostly through our login page. My hacker PUNK Coward goes by the name of devil-z tim of the Dark Devilz Clan of Turkish Hackers spouting the Koran and the plight of African Muslims via all of my Past Income producing Blogs. If I could get 10 Mins. alone with this punk I would
          give him a HACKING he would both never forget and never remember if you know what I mean. Anyway I thought misery would love company……I am still dead in the water as I haven’t figured out how to rid the world and
          My Blogs of this wart on the Butt of the world.

  16. Note that fixing the vulnerabilities – really just swapping out for the new timthumb.php file – is just the FIRST thing you should do. That said, it’s clear the authors created backdoors to access sites even after timthumb.php has been fixed.

    I’m finding a few scattered files that needed to be deleted…
    /wp-admin/js/config.php
    /wp-admin/common.php
    /wp-admin/udp.php
    /wp-content/udp.php

    • Thanks for the comment Steve. Yes that’s exactly what I’m seeing. I’ve repaired several hacked WP sites in the last week and in every case the first thing the attacker did was to upload a php script either URL encoded or base64 encoded that lived outside the timthumb cache directory, so they would have continued access.

  17. Hello,

    I use Stufe, a theme from themeforest and I’ve been hacked like everyone else. The problem is that I am a writer not a developer and have very scratchy knowledge of how to fix this. it is really stressing me out. Is anyone able to take a look at my site http://www.fennelandfern.co.uk and tell me where the code is so I can dispose of it?
    Thanks so much.

  18. Question: We, too, were victimized by this exploit. The odd thing is that it only showed up in one way: Macintoshes were not redirected, nor were PC’s *except* for those clicking on the link provided on the site owner’s Facebook page. The lins on that page, posted automatically when each post is published, are routed through facebook with some sort of hash number I suppose is designed to authenticate the link redirect. I thought the problem might be the URL shortener, but the problem occurred either way. E.g., http://ow.ly/62vj6 (the site has been repaired, of course)

    Any idea why just one route resulted in spamsville? I’m suspecting a defect in Internet Explorer, the probable brower used.

  19. Hi,

    i run alot of wordpress sites and i had to write a wee script to scan through all my files and look for unsecure versions, my script also gives you the option to upgrade the script while still keeping the correct location for your cache directory. It also scans your files for know spam code just incase the damage has already been done.

    My Script is on google code as “timthumb-updater” here >http://code.google.com/p/timthumb-updater/downloads/list

    I also found the Alucar shell script that was installed on your server, in ran it on my server and watched to see what it did, it sends an email probably with the login details to danhchohack@yahoo.com

    All my sites are updated now, thanks for your good work…

    Stiofan

  20. Where are the thumbnails being stored now? I see new files in my when adding a new photo, cache folder: timthumb_ext_some number.timthumb.txt. Opening the file shows a php code with die execution denied! a few more lines of readable code and then encrypted code. Should I delete this cache folder? Are my previous added photos using it?

    In the script file I see define (‘FILE_CACHE_DIRECTORY’, ‘./cache’); Directory where images are cached. Left blank it will use the system temporary directory (which is better for security). What temporary directory and where would I find that? Should I name a new cache directory in case I would ever what to move my site?

    Thanks for all you have done on this script. You are life saver to all of us that are using the script.

  21. Many thanks for what you’ve done here in fixing this and providing WordThumb. For the millions of non-techies, do you mind publishing (perhaps on the home page of the Google Code page) a simple set of instructions for replacing TimThumb with WordThumb? I can go as far as FTP and even code tweaks, but I’m assuming if I simply delete TimThumb.php and upload WordThumb.php, the code in my current WP sites won’t know how to address it automatically unless I tell it how. Can you enlighten? Thanks in advance!

    • Delete the timthumb.php file and upload wordthumb.php. Then search and replace theme files for anything referencing timthumb. Anywhere you see timthumb, substitute wordthumb.

      I also changed the name of the timthumb folder to resize. My own personal choice. If changing the folder name, again search for references to the folder and replace timthumb with your chosen folder name.

      Someone correct me if I’m wrong, but these steps are all it’s taken to get it working flawlessly for me.

  22. Just a quick note on eval(base64 bit). The encoded part can be “decoded” using online tools (search for base64 decode). It isn’t always vicious stuff in there (sometimes it’s just a “free theme” author that wants to hide their attribution link and prevent people removing it – They do want to get credit for their work, after all :) ) So instead of checking if there is just a few occurances, look for trends. Like, one of my sites had EVERY file update at (or around) the same time when I got infected years ago. The base64 bit WAS there in each of them, and it WAS nasty :P I was younger then, that was pretty much a “pull the plug, she’s never gonna make it!” situation.

    • To suggest that a free theme author using the eval base64 nonsense is not “vicious stuff” misses the point.

      All code in a theme or plugin is supposed to be open, including that link. I personally find it offensive and spammy when theme or plugin authors encode a credit and link n their work.

      By using code that is not human readable, they are violating if not the the terms, then at least the spirit of any open source license.

  23. Do we need to worry about inactive themes in the theme dir? I have a few extras that I was trying out for a possible switch in future. I guess I could only have active one and default but just wondering. Also my sons nerf site’s theme Albizia is on list but I could not find the timthumb or thumb.php files.
    Is there a was to fix for my whole vps for all sites in just one place/file instead of going thru all site’s dir?

      • I will delete my unused themes bc it sounds easier. It will save a bit of space too i guess. I also noticed some of the Timthumbs/thumbs I found had diff code, some had the part to delete and some did not. Some had other code included not in the update you mentioned. Should we add to or replace or how to do if it here is more code. Arras theme has the allowsites edit part on line 542. Is just taking out the allowedsites list the fix in update? If it is.. good but if the update addresses other problems then at least the allowedsites I can fix. This file is used by most of the themes I like! :(

          • Sry for being so dense but your saying to replace the old timthumb with new updated one even tho the old has more code in it than the new one. Some have a lot more lines of code that the new does not have. Thanks!

  24. Thank you very much for your article.
    But you didn’t explain one thing : how did your hacker use the thimthumb module?
    I think it’s only for the administrator or the contributors, when they make an article and they want to put an image, no?

  25. Use at your own risk.. mass find and replace.

    This removes the allowed sites array entires from *thumb.php at least it did for me.

    find . -iname ‘*thumb.php’ -exec replace “‘flickr.com’,” “” — {} \;
    find . -iname ‘*thumb.php’ -exec replace “‘picasa.com’,” “” — {} \;
    find . -iname ‘*thumb.php’ -exec replace “‘blogger.com’,” “” — {} \;
    find . -iname ‘*thumb.php’ -exec replace “‘wordpress.com’,” “” — {} \;
    find . -iname ‘*thumb.php’ -exec replace “‘img.youtube.com’,” “” — {} \;

    • ..and wrapped in sorry.


      find . -iname '*thumb.php' -exec replace "'flickr.com'," "" -- {} \;
      find . -iname '*thumb.php' -exec replace "'picasa.com'," "" -- {} \;
      find . -iname '*thumb.php' -exec replace "'blogger.com'," "" -- {} \;
      find . -iname '*thumb.php' -exec replace "'wordpress.com'," "" -- {} \;
      find . -iname '*thumb.php' -exec replace "'img.youtube.com'," "" -- {} \;

      • Thanks Peter, now the question is: how secure is to install the ‘sucuri’ script while the main issue here is that installing scripts without tech knowledge could create the same result as timthumb?

        Did somebody tested the script from sucuri.net and would safely recommend it to run in any WP or PHP based site?
        Thanks for the reply!

        • Well, that’s probably an appropriate response. Sucuri seems to be a legitimate business, and they seem to know their stuff – so, while there is some risk there (if you don’t know enough to audit the code yourself), I’d say in this case it’s fairly low.

          I haven’t tested the script from sucuri, nor have I looked over it too closely – but personally, I’d probably trust them.

          You should, however, make sure to remove the script after you’re done using it.

  26. Do you know if timthumb allowed the upload of a file with the extension .php? Or did it allow the upload of a file with a double extension like badscript.php.jpg?

  27. Hey everyone,
    Thanks for the headsup and all the tips throuhgout…

    To add my two cents to the arguments of using timthumb vs other methods like WordPress functions… There are definitely some cases where the WP functions just do not do the job. Not as is anyway. When creating thumbnails on the fly, it would be possible to use a combo of WP functions but there is not an easy one out there right now. The built in thumbnail functions are completely different than timthumb and not a replacement.

    In my case I need to allow images from external sites so emptying the array or shutting that off is not a solution either. I imagine there are others who are in the same spot.

    Here are the fixes I have added so far. I am using a somewhat modified version of the timthumb script so forgive some differences with the line numbers, etc…

    Any input greatly appreciated.

    1) To prevent any crawling and finding the timthumb script, I simply renamed it and replaced all mentions of it in my plugins with the new name. At least make it harder to find.

    2) I added an .htaccess file in the cache folder with the following thanks to the tips from Vinh NGuyen and Mark H:


    # Turn on URL rewriting
    RewriteEngine On
    Order Deny,Allow
    Deny From All

    Options -ExecCGI
    AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi

    3) I added a quick strpos filter to the “check_external” function that at least makes sure it does not contain a .php or .js extension and makes sure it does include a valid image extension:


    function check_external ($src) {

    global $allowedSites;

    if ( ( strpos( $src , ".php" ) || strpos( $src , ".js" ) || strpos( $src , "<?php" ) ) || ( !strpos( $src , ".jpg" ) && !strpos( $src , ".gif" ) && !strpos( $src , ".jpeg" ) && !strpos( $src , ".png" ) ) )
    return;

    End result should be that php files are not uploaded in the first place and if they are they cannot be executed. Am I missing anything?

    • Hey Marty – have you also updated to the latest TimThumb? There are a number of fixes added that will help the situation quite a bit

      • Hey Ben,
        I haven’t as I am using a modified version of not even the latest version before that :) Will get around to it one day but when I first tried upgrading it broke everything and did not have the time to figure out why just now.

        btw – are you the Ben that said you are one of the timthumb authors? I came up with a URL rewriting method to hide the timbthumb script and make all the urls look like image urls, if you’re interested I can send you what I have. This was before this issue, more for SEO/pretty url reasons than security.

        That is is the main reason I cannot just upgrade to the new one. :) But will give it a shot when I get a minute.

          • Awesome. Will do. Just took a quick look at the new code and added the mimetype check that you have in the check_extenal function too. Thanks!

            Give me a day or to and I’ll send that rewrite info!

  28. I was just going through all of our sites and modifying all of the timthumb/thumb.php scripts when I noticed that the popular WP plugin ‘OnSwipe’ comes with a modified version of the script.

    The thumb author adds the following at the beginning of the script;

    // I’ve modified it so it stores it’s cache outside the theme folder
    $cache_dir = dirname(dirname(dirname(dirname(dirname(__FILE__))))).”/uploads/thumb-cache”;

    if (!is_dir($cache_dir)) {
    mkdir($cache_dir,0777,true);
    }

    Any thoughts on whether this would be a worthwhile addition to the security-tightening measures already listed?

        • by default, it’s only available to images that are uploaded after a new size has been defined. you’d have to regenerate all images if you want to modify anything within your theme for the new size. all sizes defined will be created for everything uploaded into your site.

          with timthumb, you can adjust sizes on the fly and images will only be generated that are actually used. timthumb has a bunch of built in features that provide functionality that you can’t do with wordpress.

          timthumb is a very useful tool that has its place in theme development.

          • When issues such as this arise there are always those who declare rather haughtily that you should only need to use the built-in WP functions.

            Just to clarify for anyone who might be confused by such an assertion, there is NO one-size-fits-all solution and anyone who says so has probably never pushed the boundaries of website design and functionality.

            If your website *only* publishes standard blog posts or news content with at least one image per post then sure you can use the WP API but if you use a fluid design, or a BuddyPress/Multisite network where images might be embedded in a page prior to being grabbed for display then you’ll probably need some sort of resizing script.

            It’s a compromise between design/functionality and simplicity – you COULD use a standard cookie-cutter format limited by the WP API functionality, but that’s the kind of recipe which leads to boring uniformity.

      • Thanks for the heads up Mark. Timthumb is so widely used that it is almost impossible to find a premium theme without using it. I hope the timthumb guys release an update with the vulnerability fixed. I have been using the wordpress built-in image cropping for themes. But also have quite a few themes with the timthumb solution. I will be following this issue.

  29. I was looking at using Timthumb because I have all my images off on photobucket. The internal WP cropping and sizing won’t work on external images.

    I don’t want image leeches spiking my bandwidth.

    Is there a plug-in or way to draw in external images to create thumbnails to use on the WP site?

  30. I just wanted to add that there are a lot of themes out there that also names the file thumb.php

    Please check for this files. If you SSH:

    #: find . -name “thumb.php”

    All of the WooThemes on my network has this. Time to let their developers know.

  31. Hey Mark, thats a great advice, to be honest, I never thought of looking into timthumb.php because I always assumed that a priviledged site should be added manually or per option and not be inserted by default.

    I’ll definately pass on your advise.
    Thank you very much!

  32. This is a quite misleading title… the issue is with TimThumb.php which isn’t a part of the WordPress core but a common theme and plugin file; not a WP vulnerability, but a 3rd party author issue.

    Please be a bit more clear with your titles.

  33. Someone needs to teach the timthumb author how to use the ^ and $ in regular expressions. This isn’t that hard of a problem but you have to use beginning of line and end of line regexp to solve it.

  34. Don’t forget the possibility of multiple extensions e.g. .php.gif when checking filenames. I recall that ‘mod-mime’ will result in some variants being treated as PHP.

  35. Would adding these htaccess rules to the cache directory be effective?
    (prevents php and some other scripting languages from being executed there)

    Options -Indexes
    Options -ExecCGI
    AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi

  36. Also everybody. Be nice. Don’t blame timthumb’s author. He done a great job without getting paid. And all of us used timthumb and got advantage from it for a long time. But how many in us made a donation to him?

    So when an issue happened like this issue, discuss and fix it.

    Mark also done a great job on it and I plan to continue using timthumb.

  37. I’m thinking why not putting a .htaccess in cache folder to prevent directly access to any files in this folder.

    Just a simple file like:

    # Turn on URL rewriting
    RewriteEngine On

    Order Deny,Allow
    Deny From All

    will do the job.
    Also we can move the cache to a folder out of root dir. As long as we define correctly “cache” path:
    define (‘DIRECTORY_CACHE’, ‘./cache’); // cache directory

  38. And how do you resize the images without a resize script that can write files? You are suggesting to remove timthumb, but wordpress can write files too, than what do you do? Remove wordpress? ( this question is considering users that do not know how to resize them themselves – 80% )

  39. I’ve always liked the idea of TimThumb. Fortunately, I’m a bit to anal to let a script futz with my images too much.

    Nice find, btw. Thanks for your hard work.

  40. Rather than edit the timthumb.php file, you could pop a .htaccess file into the cache folder with something like the following:

    Options -ExecCGI
    AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi

    • Sorry, should have explained what it does…

      It simply makes any attempt to access the files with the quoted extensions result in – 403 Forbidden – Access is Denied

  41. This script is inherently insecure, and its usage is a sign of poor coding.

    If you have a theme or plugin that requires thsi script, I STRONGLY reccomend rewriting the code to use the relevant WordPress APIs.

    WordPress already has a comprehensive image handling system that integrates far better than timthumb, is far more secure, does not write files into the themes folder, and keeps them in the same place as uploaded post files.

    Since it’s a part of WordPress Core, its far safer to use, and is updated as you update WordPress.

    http://codex.wordpress.org/Function_Reference/add_image_size


    the_post_thumbnail(); // without parameter -> Thumbnail

    the_post_thumbnail('thumbnail'); // Thumbnail (default 150px x 150px max)
    the_post_thumbnail('medium'); // Medium resolution (default 300px x 300px max)
    the_post_thumbnail('large'); // Large resolution (default 640px x 640px max)

    the_post_thumbnail( array(100,100) ); // Other resolutions

    http://codex.wordpress.org/Function_Reference/wp_get_attachment_image_src

    Also this removes the problem of people taking your timthumb.php and using it to cache *other* things, AND it lets you keep the references to alternate sites since WordPress can download them and save them as attachment posts.

    You also gain the cropping UI functionality etc etc etc

    • Cannot agree more!
      This timthumb.php has a code written even worse than the WordPress code itself!
      The fix is quite good, but I really suggest anyone to look for a different library for image resizing, as timthumb.php could have been exploited even more!
      It is a shame that WordPress libraries, plugins and caches are accessible from the document root :(

  42. I’m a non-coder and thanks to your little grep scanning code, I just found out I’ve been bitten by the is-human exploit! I’m feeling rather violated at the moment. So far, the only info I’m finding is a link to the is-human exploit-db page (http://www.exploit-db.com/exploits/17299/) .

    Have you had the (dis)pleasure of running into this particular gem? Any pointers would be greatly appreciated and thanks for this post because I would’ve been blissfully unaware.

    Jane

  43. Just a thought and I apologize in advance if this is stupid.

    Would installed security Plugins like WP Firewall and Block Bad Queries keep a site using the timthumb script safe from this hack?

    • Most certainly not, those plugins cannot prevent these kinds of issues. They do improve security, but only by a minimal amount by closing some holes. They cannot and should not be relied upon for comprehensive security.

  44. An alternative hotfix would be:

    1. Completely comment out the function checkExternal()
    2. Creater a dummy checkExternal function just like the following one:

    function checkExternal( $src ) {
    if (stripos($src, ‘http://’) !== false) {
    $url_info = parse_url ($src);
    displayError(‘remote host “‘ . $url_info['host'] . ‘” not allowed’);
    }
    }

    This one has the advantage of BOTH blocking all external calls AND avoiding a possible nasty PHP error which could popup by cycling through an empty array in the allowedSites-foreach loop.

    cu, w0lf.

  45. I found and opened the timthumb.php file in my (self-hosted) WordPress installation, and searching the string “$allowedSites” (or “$allowed”, “allowed”, etc.) returned no results. It seems that there’s no

    $allowedSites = array (

    line at all. But then again, I’m using a rather old WP Theme, so I’m probably having an equally old version of timthumb.php. Should I worry anyway?

    Thank you, and kind regards —
    RM

  46. Hi all – I am the developer of TimThumb. I can’t apologise enough for this oversight in the code and hope nobody has anything too bad happen to their sites because of my error.

    Mark has been really helpful in solving the issue and I have worked with him to harden up the script. At the moment the best fix is to simply use the latest version of TimThumb. There have been a stack of tweaks that will make the script harder to abuse.

    I anyone wants to audit the code, or offer any help or suggestions for improving the security of TimThumb then I am all ears.

  47. Something like

    diff timthumb.old timthumb.php
    585c585,586
    $pattern=”/$site\z/i”;
    > if(preg_match($pattern, $url_info['host'])){

    Should do the trick, but I ain’t no php coder, so ymmv…

    • That fix may work but anyone can create a blog on blogger.com which is one of the domains allowed by default and upload code to site using timthumb.

      Here’s the bug I filed if you want to comment.

      http://code.google.com/p/timthumb/issues/detail?id=212

      I think the best long term solution is to stop allowing site visitors to write remotely loaded files to a web accessible dir. Maybe use /tmp or another store as cache instead of something under wordpress root.

  48. Just a quick note here, The latest version on GoogleCode has “fixed” the code execution issues…
    2 changesets:

    1. r141: http://code.google.com/p/timthumb/source/detail?r=141 (3 days ago)
    Checks the Mimetype of the downloaded file before saving, rejects files which do not match a image mimetype.

    Fixed? Nope. It’s easy to fool PHP’s mimetype checker, ‘GIF8<?php ..' in a file would pass those checks, as PHP thinks it's a Gif image.

    2. r142: http://code.google.com/p/timthumb/source/detail?r=142 (41 hours ago)
    Removes the file extension of the saved files, This prevents files ending up being saved as a .php file.

    Fixed? Not really.. certain Server configurations pass everything through PHP (I'd call that a badly configured server though).

    So you can still embed items from other pages by using a domain such as 'www.wordpress.com.attacker.com/' . You can still upload files containing whatever you want, however, it's unlikely that PHP would be processed. Leaves the door open for XSS/CSRF attacks for sure if the document contained HTML.

    • Sorry about the delay in approving your comment Dion, the links caused my mod system to catch it. There are a few updates on the issues page for timthumb.

  49. Not sure if this is a total fix, but here is something I added to line 719 of timthumb. It checks the file extension to make sure it’s not php, and it it does, adios.

    if(preg_match(‘/\.php$/’,$localfilepath,$bad_filenames) == 1)
    display_error(“someone is doing something they shouldn’t”);

    • Josh please see the latest version of timthumb.php because I think you’re using an older version. $localfilepath is no longer used.

      Also see my reply to you below re order of execution and mime type checking.

      • Woops, it’s local_filepath. I checked, line 719 is right.

        Basically, I’m just checking to make sure nothing with an executable suffix is going to be written directly before file_put_contents() happens.

        I think the better solution might be to just check to see if it ends in a graphical file name as people can have all kinds of silly stuff setup to execute. .jsphdphp or what have you.

  50. Hey,
    Nice write up. A couple of things:

    1) Nice work.
    2) You’d need to have changed ALLOW EXTERNAL option to true for this exploit to work. It comes as “False” default, so unless you changed it, it’s ok for now.
    3) Timthumb is old and busted, try to use the wp resizing when possible. Though I agree, I love elegant themes.

    Josh

    • Josh, my ALLOW_EXTERNAL was false when I got hacked.

      ALLOW_EXTERNAL only determines if timthumb will check the allowed array of external sites or if it will allow content to be loaded from absolutely any site…. which seems insane to me. I’ve verified this is also the case in trunk (the latest version). Here’s the code:

      if (ALLOW_EXTERNAL) {
      $isAllowedSite = true;
      } else {
      $isAllowedSite = false;
      foreach ($allowedSites as $site) {
      if (strpos (strtolower ($url_info['host']), $site) !== false) {
      $isAllowedSite = true;
      }
      }

      }

      I know. Even after this, I still love elegant themes.

      • Damnit. That’s terrible news. So you just put the URI of the site into the address containing the malicious code. Sigh. I have lots of updating to do.

        • Just working through this right now. Doesn’t this code offer some protection?
          Line 708

          !preg_match (“/jpg|jpeg|gif|png/i”, $file_infos['mime']))

          Or, can you spoof the mimetype and name the file .php with a mime type of jpg

          After all, you can’t execute code that isn’t ending in .php unless you can tinker with the server settings.

          And you can’t rename unless you have access to an exec() somewhere which is probably disabled as well.

          Thoughts? I’m new(er) at this.

          • No prob. mime_type is executed after the file is fetched at which point the hacker can already access the file directly and the web server will execute it because it has a php extension.

            timthumb.php is only used to download the file. It doesn’t execute anything. If you have a way to write a .php file anywhere under wordpress root, you can execute that using a browser and you’re in.

            I mentioned to another developer below that the code is a little hard to follow because the function names are deceiving. Execution enters clean_source, then executes check_external then that’s where it does the fetching. That all happens before mime_type is executed.

  51. Could u explain more detail on how he bypass mime checking of timthumb? I really want to know cuz I don’t have much knowledge in this field. It seems related to base64_encode ?

      • I think you are thinking I’m the guy who hacked u because of my name and I’m a Vietnamese :(! But I’m not, I’m not a script kiddie. I’m a developer who you can see me here http://axcoto.com or http://axcoto.com/blog or twitter http://twitter.com/kureikain and my contribute to wordpress http://wordpress.org/extend/plugins/profile/kureikain and my business http://codecanyon.net/user/kureikain/
        You see, I’m absolutely the kind of person who go around and hack developer’s website.

        I just want to understand fully about this error under the view of a developer.

        As I read code of timthumb.php, I see it’s checking mime type (not file extension, it really check mime type). And I dunno how the hacker passed it..

        Thank you.

        • OK sorry mate. You have the same initials as something I saw in the hackers code.

          Also the question about bypassing mime checking was a little too smart. :-)

          Looks like the code enters clean_source, then executes check_external then that’s where it does the fetching. The function names are a little deceiving.

          There is no mime checking before the external fetching occurs and once the external file is written to disk the attacker is already in. timthumb doesn’t need to output it to a browser for the attacker to gain access because they access the downloaded script directly.

  52. Wow – solid work following this all the way through.

    As you (and the previous commenter) have alluded to – timthumb is used massively in the WP community, and elsewhere. The bit at the end of this post is definitely useful, but I’m guessing most non-coders will be scared off by the rest of the post.

    It would probably be worthwhile to put together a post to explain step by step, simply, how to fix timthumb. If you’re interested, I’d be happy to help ( and even happier to link to it).

    • Hi Peter. Thanks for the suggestion. I’ve put together some step-by-step beginner instructions above. Hopefully that helps a bit. Let me know if you have feedback.

  53. If this is accurate across most server configs, I’d say this is a pretty serious issue not just for WordPress users, but for users of pretty much any CMS or site that uses timthumb!

    • I’d tend to agree. I didn’t want to sound too breathless in this post until the developer and a few smart folks have verified it. But AFAIKT it seems this will give you read or write access to anything the web server has access to.

      For example, reading wp-config.php which the web server has access to will give you a machine’s mysql db and password. The php script I screenshotted above (and that a hacker uploaded to my server) lets you take those credentials and dump the entire mysql db if you’re so inclined – or insert malicious data or drop databases.

      • Shell uploaders can also change .htaccess files if they are given write permissions. So putting a .htaccess file in your cache or other directory will do no good unless there is no write permission, eg 444.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.