The situation: The two people with root access to this server are away for the remainder of this week. An individual with a Drupal website that refused to have updates performed has had their site compromised. They have now changed their opinion and had updates installed but damage is already done. I am but a mere developer who has been asked to perform damage control until the sysadmin returns to work.

I know the ideal solution is burn it to the ground and restore an untainted backup, and then install updates immediatley but I do not have clearance to do this.

The setup: A Linux-based webserver running cpanel, nginx, PHP & MySQL

The effects I am aware of of this compromised site are:

  • A new php file with loads of nasty functionality gets created
  • The public_html/index.php file gets updated to include this file
  • The public_html/.htaccess file has 8 additional RewriteRules added

I have attempted to find compromised files by looking for recently modded files

 find . -type f -mtime -30 -printf "%M %u %g %TY-%Tm-%Td %TH:%TM:%.2TS %p\n"

And by grepping for eval - the latter led me to a very obviously newly added file with a mod date almost a year ago, so this attacker at least has the presence of mind to make my initial approach insufficiant.

So I moved onto symptom suppression. As I lack root access I cannot make my index.php / .htaccess files read-only

$ chattr +i index.php
chattr: Operation not permitted while setting flags on index.php

So I moved onto the last tool that I know I have: cron

I added commands to remove the evil php file and to remove the include from my index.php - they work fine.

However, the sed commands I created don't seem to work. They work when I manually run them, but they don't seem to from cron. I have verified the path to sed is correct, and the absolute path to .htaccess is correct. Can anyone tell me what is wrong please?

$ crontab -l
* * * * * echo -e "<?php\n/**\n * @file\n * The PHP page that serves all page requests on a Drupal installation.\n *\n * The routines here dispatch control to the appropriate handler, which then\n * prints the appropriate page.\n *\n * All Drupal code is released under the GNU General Public License.\n * See COPYRIGHT.txt and LICENSE.txt.\n */\n\n/**\n * Root directory of Drupal installation.\n */\ndefine('DRUPAL_ROOT', getcwd());\n\nrequire_once DRUPAL_ROOT . '/includes/bootstrap.inc';\ndrupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);\nmenu_execute_active_handler();\n\n" > /home/summerhillpackag/public_html/index.php 2>&1
* * * * * rm -rf /home/summerhillpackag/public_html/themes/garland 2>&1
* * * * * /usr/bin/sed -i 's/RewriteRule ^[cv](\\d+)\[-\/\][cv](\\d+)\[-\/\]\.\*$ index\\\.php?id=$[12]-$[12]&%{QUERY_STRING} \[L\]//' /home/summerhillpackag/public_html/.htaccess 2>&1
* * * * * /usr/bin/sed -i 's/RewriteRule ^\.\*\[-\/\][cv](\\d+)\[-\/\][cv](\\d+)\[-\/\]\.\*$ index\\\.php?id=$[12]-$[12]&%{QUERY_STRING} \[L\]//' /home/summerhillpackag/public_html/.htaccess 2>&1
* * * * * /usr/bin/sed -i 's/RewriteRule ^\.\*\[-\/\][cv](\\d+)\[-\/\]\.\*\[-\/\][cv](\\d+)\[-\/\]\.\*$ index\\\.php?id=$[12]-$[12]&%{QUERY_STRING} \[L\]//' /home/summerhillpackag/public_html/.htaccess 2>&1
* * * * * /usr/bin/sed -i 's/RewriteRule ^v(\\d+)\[-\/\]\.\*\[\-\/\]c(\\d+)-\.\*$ index\\\.php?id=$1-$2&%{QUERY_STRING} \[L\]//' /home/summerhillpackag/public_html/.htaccess 2>&1
* * * * * /usr/bin/sed -i 's/RewriteRule ^c(\\d+)\[-\/\]\.\*\[-\/\]v(\\d+)\[-\/\]\.\*$ index\\\.php?id=$2-$1&%{QUERY_STRING} \[L\]//' /home/summerhillpackag/public_html/.htaccess 2>&1

marked as duplicate by ilkkachu, Community May 30 '18 at 17:24

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • Do you get any errors from the cron job? – ilkkachu May 30 '18 at 16:48
  • 2
    I understand you are in a difficult position due to your constraints but you have unfortunately also to understand that it is mostly, especially without full root access, impossible to remove all nasty things that have been installed. For example, file times could be changed so that your find command would not see them. Instead of doing all the sed stuff you should probably try to find a "proper" .htaccess file and try to regularly overwrite (of course this is not the ideal solution). Your cron uses a specific shell not like yours so commands may not work because of it. – Patrick Mevzek May 30 '18 at 16:49
  • 1
    Because this looks a lot like this: What is causing my “Unexpected EOF Error while looking for …” error? and it looks like you should get the same error. – ilkkachu May 30 '18 at 16:55
  • @ilkkachu Yep, that was exactly it! Thank you – Scoots May 30 '18 at 17:24
  • 1
    Yes, I think so. And I do not know why your question was marked as duplicate as it has nothing to do with the other one anyway. You should also really attempt to solve the core problem: that is start from scratch with another server and backups as this one is a lost cause. – Patrick Mevzek May 30 '18 at 17:32

Browse other questions tagged or ask your own question.