How to check if your drupal site was hacked (and how to fix it)

Install drupalgeddon on your server:

drush dl drupalgeddon

Install Site Audit:

drush dl site_audit --dev

Install Hacked:

drush dl hacked --dev; drush en hacked -y

Install Security Review:

drush en security_review -y

OPTIONAL: run all the above in a single line.

drush dl drupalgeddon -y; drush dl site_audit --dev -y; drush dl hacked --dev -y; drush en hacked -y; drush en security_review -y

Run the drupalgeddon site audit--this will also run the above modules--this will create a file called 'report.html'. Open it up and see what's up.

Identify and remove hacked files, nodes, modules

drush aa --html --bootstrap --detail --skip=insights > ./report.html

Look for suspicious files and/or directories, and delete those. Follow additional security recommendations.

Run Hacked via Drush

Show all modified projects/modules:

drush hacked-list-projects --force-rebuild

After, do this for each project/module that it shows as changed (substitude changedproject with whatever is listed):

drush hacked-details changedproject

Also run this after to show additional files/directories that don't exist in the project/module:

drush hacked-diff changedproject

Drupalgeddon:

drush asec

Drush delete users

drush user-cancel username
drush ucan username

Drush reset first user/admin pass

drush uli

Drush change user pass

drush user-password username --password="NEWPASS"
#or 
drush upwd username --password="NEWPASS"

Run /admin/reports/security-review/ in drupal admin

Find and remove hacked files

find . -size 494c -name "*.php"
 
# you can remove these like so:
find . -size 494c -name "*.php" | xargs rm

Locate PCT4B injected existing files

grep -Rl PCT4BA6ODSE .
# and
grep -Rl  q6ae4d5 .

Locate various injected files

grep -Rl SOL_TCP .
grep -Rl SOCK_STREAM .
grep -Rl SOCK_DGRAM .
grep -Rl SOL_UDP .
grep -Rl SO_REUSEADDR .
​grep -Rl SO_RCVTIMEO .
​​grep -Rl SO_SNDTIMEO .

Once you identify the infected files, search the apache log files and block any IPs accessing that file.

cd /var/log/httpd/
grep -iR 'NAME_OF_MALICIOUS_FILE.php' .

If you do find any files, then the best thing is to delete the module and re-download it

Set proper file permissions

cd /DRUPAL_DIR
find . -type d -print0 | xargs -0 chmod 755; find . -type f -print0 | xargs -0 chmod 644; chmod 777 sites/default/files; find ./sites/default/files -type d -print0 | xargs -0 chmod 777; find ./sites/default/files -type f -print0 | xargs -0 chmod 666;

Or create and run this script.

Make sure you convert the line breaks to UNIX/OSX format instead of Windows.
( Notepad++ can easily do this. Under Edit --> EOL Conversion --> UNIX/OSX format )

Run like so:

/usr/local/bin/fix-permissions.sh --path=/home/USER/public_html --user=USER --group=GROUP

This is the actual script

#!/bin/bash
# Help menu
print_help() {
cat <<-HELP
This script is used to fix permissions of a Drupal installation
you need to provide the following arguments:
1) Path to your Drupal installation.
2) Username of the user that you want to give files/directories ownership.
3) HTTPD group name (defaults to www-data for Apache).
Usage: (sudo) bash ${0##*/} --path=PATH --user=USER --group=GROUP
Example: (sudo) bash ${0##*/} --path=/usr/local/apache2/htdocs --user=john --group=www-data
HELP
exit 0
}
 
path=${1%/}
user=${2}
group="${3:-apache}"
# Parse Command Line Arguments
while [ $# -gt 0 ]; do
  case "$1" in
    --path=*)
      path="${1#*=}"
      ;;
    --user=*)
      user="${1#*=}"
      ;;
    --group=*)
      group="${1#*=}"
      ;;
    --help) print_help;;
    *)
      printf "***********************************************************\n"
      printf "* Error: Invalid argument, run --help for valid arguments. *\n"
      printf "***********************************************************\n"
      exit 1
  esac
  shift
done
if [ -z "${path}" ] || [ ! -d "${path}/sites" ] || [ ! -f "${path}/core/modules/system/system.module" ] && [ ! -f "${path}/modules/system/system.module" ]; then
  printf "*********************************************\n"
  printf "* Error: Please provide a valid Drupal path. *\n"
  printf "*********************************************\n"
  print_help
  exit 1
fi
if [ -z "${user}" ] || [[ $(id -un "${user}" 2> /dev/null) != "${user}" ]]; then
  printf "*************************************\n"
  printf "* Error: Please provide a valid user. *\n"
  printf "*************************************\n"
  print_help
  exit 1
fi
cd $path
printf "Changing ownership of all contents of "${path}":\n user => "${user}" \t group => "${group}"\n"
chown -R ${user}:${group} .
printf "Changing permissions of all directories inside "${path}" to (755) "rwxr-xr-x"...\n"
find . -type d -print0 | xargs -0 chmod 755;
printf "Changing permissions of all files inside "${path}" to (644) "rw-r--r--"...\n"
find . -type f -print0 | xargs -0 chmod 644;
printf "Changing permissions of "sites/all/modules" directories in "${path}/sites/all/modules" to (755) "rwxr-xr-x"...\n"
cd $path/sites/all/modules
find . -type d -print0 | xargs -0 chmod 755;
printf "Changing permissions of all files inside "${path}/sites/all/modules" to (644) "rw-r--r--"...\n"
find . -type f -print0 | xargs -0 chmod 644;
printf "Changing permissions of "modules" directories in "${path}/modules" to (755) "rwxr-xr-x"...\n"
cd $path/modules
find . -type d -print0 | xargs -0 chmod 755;
printf "Changing permissions of all files inside "${path}/modules" to (644) "rw-r--r--"...\n" 
find . -type f -print0 | xargs -0 chmod 644;
printf "Changing permissions of all directories inside all "files" directories in "${path}/sites" to (666) "rw-rw-rw-"...\n"
cd $path/sites
find . -type d -name files -print0 | xargs -0 chmod 777;
printf "Changing permissions of all files to 666 and directories to 777 inside all "files" directories in "${path}/sites" \n"
for x in ./*/files; do
    find ${x} -type d -print0 | xargs -0 chmod 777;
    find ${x} -type f -print0 | xargs -0 chmod 666;
done
echo "Done setting proper permissions on files and directories"

Run like so:

/usr/local/bin/fix-permissions-strict.sh --drupal_path=/home/USER/public_html --drupal_user=USER --httpd_group=GROUP

This is the actual script

#!/bin/bash
# Help menu
print_help() {
cat <<-HELP                                                                                                                                                                                                                                                     
This script is used to fix permissions of a Drupal installation
you need to provide the following arguments:
1) Path to your Drupal installation.
2) Username of the user that you want to give files/directories ownership.
3) HTTPD group name (defaults to www-data for Apache).
Usage: (sudo) bash ${0##*/} --drupal_path=PATH --drupal_user=USER --httpd_group=GROUP
Example: (sudo) bash ${0##*/} --drupal_path=/usr/local/apache2/htdocs --drupal_user=john --httpd_group=www-data
HELP
exit 0
}
if [ $(id -u) != 0 ]; then
  printf "**************************************\n"
  printf "* Error: You must run this with sudo. *\n"
  printf "**************************************\n"
  print_help
  exit 1
fi
drupal_path=${1%/}
drupal_user=${2}
httpd_group="${3:-apache}"
# Parse Command Line Arguments
while [ $# -gt 0 ]; do
  case "$1" in
    --drupal_path=*)
      drupal_path="${1#*=}"
      ;;  
    --drupal_user=*)
      drupal_user="${1#*=}"
      ;;  
    --httpd_group=*)
      httpd_group="${1#*=}"
      ;;  
    --help) print_help;;
    *)  
      printf "***********************************************************\n"
      printf "* Error: Invalid argument, run --help for valid arguments. *\n"
      printf "***********************************************************\n"
      exit 1
  esac
  shift
done
if [ -z "${drupal_path}" ] || [ ! -d "${drupal_path}/sites" ] || [ ! -f "${drupal_path}/core/modules/system/system.module" ] && [ ! -f "${drupal_path}/modules/system/system.module" ]; then
  printf "*********************************************\n"
  printf "* Error: Please provide a valid Drupal path. *\n"
  printf "*********************************************\n"
  print_help
  exit 1
fi
if [ -z "${drupal_user}" ] || [[ $(id -un "${drupal_user}" 2> /dev/null) != "${drupal_user}" ]]; then
  printf "*************************************\n"
  printf "* Error: Please provide a valid user. *\n"
  printf "*************************************\n"
  print_help
  exit 1
fi
cd $drupal_path
printf "Changing ownership of all contents of "${drupal_path}":\n user => "${drupal_user}" \t group => "${httpd_group}"\n"
chown -R ${drupal_user}:${httpd_group} .
printf "Changing permissions of all directories inside "${drupal_path}" to "r-xr-x---"...\n"
find . -type d -exec chmod u=rx,g=rx,o= '{}' \;
printf "Changing permissions of all files inside "${drupal_path}" to "r--r-----"...\n"
find . -type f -exec chmod u=r,g=r,o= '{}' \;
printf "Changing permissions of "sites/all/modules" directories in "${drupal_path}/sites/all/modules" to "r-xr-x---"...\n"
cd $drupal_path/sites/all/modules
find . -type d -exec chmod u=rx,g=rx,o= '{}' \;
printf "Changing permissions of all files inside "${drupal_path}/sites/all/modules" to "r--r-----"...\n"
find . -type f -exec chmod u=r,g=r,o= '{}' \;
cd $drupal_path/sites
find . -type d -name files -exec chmod ug=rwx,o= '{}' \;
printf "Changing permissions of all files inside all "files" directories in "${drupal_path}/sites" to "rw-rw-r--"...\n"
printf "Changing permissions of all directories inside all "files" directories in "${drupal_path}/sites" to "rw-rw-r--"...\n"
for x in ./*/files; do
    find ${x} -type d -exec chmod ug=rwx,o=r '{}' \;
    find ${x} -type f -exec chmod ug=rw,o=r '{}' \;
done
echo "Done setting proper permissions on files and directories"

Check your log files

Run the following command--see full explanation here:

grep cwd /var/log/exim/mainlog | grep -v /var/spool | awk -F"cwd=" '{print $2}' | awk '{print $1}' | sort | uniq -c | sort -n

Source: http://help.directadmin.com/

The first place you should go when trying to debug a problem is the log file for that program. The list of Log Files are as follows:

DirectAdmin:

/var/log/directadmin/error.log
/var/log/directadmin/errortaskq.log
/var/log/directadmin/system.log
/var/log/directadmin/security.log

Apache:

/var/log/httpd/error_log
/var/log/httpd/access_log
/var/log/httpd/suexec_log
/var/log/httpd/fpexec_log
/var/log/httpd/domains/domain.com.error.log
/var/log/httpd/domains/domain.com.log
/var/log/messages (generic errors)

Proftpd:

/var/log/proftpd/access.log
/var/log/proftpd/auth.log
/var/log/messages (generic errors)

PureFTPd:

/var/log/pureftpd.log

Dovecot and vm-pop3d:

/var/log/maillog
/var/log/messages

named (bind):

/var/log/messages

exim:

/var/log/exim/mainlog
/var/log/exim/paniclog
/var/log/exim/processlog
/var/log/exim/rejectlog
#replace 'username' with actual username
/home/username/.php/php-mail.log

(on FreeBSD, they have "exim_" in front of the filenames)

mysqld:

RedHat:

/var/lib/mysql/server.hostname.com.err

FreeBSD and Debian:

/usr/local/mysql/data/server.hostname.com.err

crond:

/var/log/cron

To view a log file, run:

less /var/log/filename

Where /var/log/filename is the path of the log you wish to view. If the log is too large you can use the "tail" command:

tail -n 30 /var/log/filename

Where 30 is the number of lines from the end you wish to view.

Delete bounced and frozen emails in exim

Set exim.conf to automatically delete bounced and frozen emails

vi /etc/exim.conf 

Set the following:

ignore_bounce_errors_after = 0h
timeout_frozen_after = 0h

Remove frozen exim emails

exipick -zi | xargs exim -Mrm

Remove the entire mail queue

exim -bp | awk '{ print $3 }' | xargs exim -Mrm

Remove mail queue older than 1 day

exiqgrep -z -o 86400 -i | xargs -r exim -Mrm 

Setup a sending email limit in exim

vi /etc/virtual/limit_USER
#add the max amount of emails you want to allow per day... example: 300
Tags: Drupal hack security drupalgeddon