Recover compromized Linux server

If you are reading this article than your site has been hacked. You have seen that spam is being sent from your server and you can’t figure out what to do with it.


It is important not to panic, but strictly follow the instructions:

  1. Scan your server using the following utilities:
  2. Make sure that spam is sent from your server

Deleting a couple of dozen files does not mean that everything is over because the utilities will only find what they know about and what they know far from everything.

You need to fiddle a little with your hands. Go to the folder with the site files and put everything in read-only mode:

find. -type f -exec chmod 444 {} \;
find. -type d -exec chmod 555 {} \;

Next we start looking for the use of the eval function:

grep 'eval(\|assert(\|gzinflate(' * -RI |cut -d `:` -f 1|grep -color '\.php' |sort -u
grep 'eval (\|assert (\|gzinflate (' * -RI |cut -d `:` -f 1|grep -color '\.php' |sort -u
grep "@.\*\$GLOBALS\['" \* -RI |cut -d `:` -f 1 |sort -u

But I encountered the reverse of the eval and base64_encode functions just today:

grep 'edoced_46esab\|lave' * -RI |grep 'strrev' |sort -u

As a result, you get a list of files. You need to open each and see what’s in it.

Even if you are not an experienced administrator or coder you will be able to distinguish between normal code and malicious code. Here is the first example: Screenshot from 2015-08-24 16:36:53

Here is a second example: Screenshot from 2015-08-24 16:39:07

The hardest part is finding the so-called ‘backdoors’. As a rule they are being hidden in the huge file in the form of quite ordinary code so it is difficult to find it.

To catch a criminal you have to think like a criminal.


If I were writing a backdoor I would not want my script to write any errors to the logs. Otherwise a smart admin would quickly see them. To do this I would turn off logging using the php error_reporting function

You can search for it:

grep `error_reporting \*(.\*0.\*)` \* -RI |cut -d `:` -f 1 |grep php

Just in case I would remove the value of error_log using ini_set:

grep "\@ini_set('error_log'" * -RI |cut -d ":" -f 1 |grep php

In order to get the path to the current directory I would use the getcwd() function:

grep "\@getcwd\(\)" * -RI |cut -d ":" -f 1 |grep php

As a result of executing each command you’ll get a list of files and you need to open each of them and see the contents.

Delete the malicious code, rename the files and reate a new empty file with the same name and forbid its editing. The safest way to do this is with the chattr utility:

chattr +i **/path/to/file**.php

It is recommended to disable the following functions in php.ini:

  • passthru
  • system
  • shell_exec
  • exec
  • popen
  • proc_open
  • curl_multi_exec
  • parse_ini_file
  • show_source
  • pcntl_exec
  • getenv
  • getmygid
  • extract
  • parse_str

Find the line disable_functions in the php.ini file and list them separated by commas. Don’t forget to restart apache after applying the changes.

In the case of Shared Hosting you can usually edit php.ini directly from the control panel. Unfortunately functions can only be disabled in php.ini. You won’t be able to put them in .htaccess.

Attention: After such changes, problems may begin with your site. Test it carefully and make sure that disabling features did not cause problems. In order to fix problems look for patches and updates for the modules of your site. Look for replacement functions at The fewer features you turn back on the less likely the problem will recur.

Immediately in the folder where the files are uploaded (uploads, media, files) I recommend to create an .htaccess with the following content:

<FilesMatch ”\.php$”>
    Deny from all

This will prevent access to the php files in the folders that are intended to be used for media. Even if you make the downloads folder writable nothing malicious can be launched from it.

Then we monitor the server for several days/nights/weeks. In case of resumption of problems - we read the logs we try to determine how the new worm appeared in the site folders. We search for it again and delete it.

Next you got to consider options for moving to a new server and updating everything that is possible (php, apache, nginx, plugins, site CMS).

Just in case you can use the following utilities to check your website: