Free command-line WordPress malware scanner

Introduction

If you have a site that has been attacked and are unable to log on to the site it can be a major pain in the ass to repair and clean it. Many hosting providers do not provide an offline malware scanner for WordPress installations and will try to upsell you security stuff if you call them and ask for help.

Another consideration is that when a site is attacked the attackers are potentially able to place malware and infect files OUTSIDE of your WordPress directory. So even if you could log in to your hacked site and run a malware scanner, it might miss potential malware files outside of its directory.

I decided to investigate this and have devised a nice way to be able to scan and clean your entire hosting directory and any WordPress sites it contains. The script can scan your entire directory or just one site or even part of one site.

To do all this you have to log into to your server using SSH. These commands are performed from a BASH shell.

1. Log in to your hosting provider via SSH

2. Clone php-malware-scanner from Github
mkdir downloads
cd downloads
git clone https://github.com/scr34m/php-malware-scanner.git

3. Create your bin directory if it doesn’t exist
cd # change back to home dir
mkdir bin # make bin dir if you don’t already have it

grep bin .bash_profile

This last step should output something like:
PATH=$PATH:$HOME/.local/bin:$HOME/bin

if not you need to add it.

4. Copy my script
Put it in a file called scan-malware.sh or another memorable name of your choosing.

Note: This script is a little sloppy, especially with the way it processes the log file. This is because the malware scanner adds ANSI color coded output to the file which is a PITA. I have to strip out the ANSI color codes and other extraneous characters in the file.

#!/bin/bash -e

SCANNER="~/downloads/php-malware-scanner/scan.php"
LOGFILE="php-malware-scanner-`date +%Y.%m.%d-%T`.log"

# Check for directory argument
if [ -z $1 ]; then
  printf "Exiting.  Must specify a directory to scan.\n"
else
  SCANDIR=$1
fi

# Execute the scanner
php $SCANNER -d $SCANDIR 2>&1 |tee ${LOGFILE}.tmp

# Remove ansi color crud from output file
sed -r "s/\x1b\[([0-9]{1,2}(;[0-9]{1,2})?)?m//g" < ${LOGFILE}.tmp > ${LOGFILE}.noansi

# Ingore OK files.  
grep '^# ER #' ${LOGFILE}.noansi > ${LOGFILE}.err

# Remove '# ER # {' at begging of line
perl -pi -e 's/^# ER # {//' ${LOGFILE}.err

# Remove curly brace at end of line
perl -pi -e 's/}$//' ${LOGFILE}.err

mv ${LOGFILE}.err $LOGFILE

printf "Finished scanning.\nLogfile saved to: $LOGFILE \n"

5. Run the script
To run the script you must supply a directory path as the only argument, so:
scan-malware.sh ~/public_html

The above example uses the ~ alias for home directory but I recommend using absolute pathnames:
cd public_html; pwd

6. Check the output, remove false positives
This script will output a text file containing the paths of all potentially malicious files in the scanned directory.

You need to go through the output file and check the lines very carefully. MAKE SURE you delete any lines for files that are not malware. Also not that some files from security plugins like Wordfence Security will test positive but they should be deleted from the output file before you feed it to the script below. You will notice Wordfence files through the path and through names that contain ‘wf’.

7. Feed the output into the clean script
Next you will need to feed this info into anther script which deletes all the files. Here is another script I’ve been using that does something like this, yet it has not been refined to work with the above output file yet:

#!/bin/bash -e

INFILE="~/malfiles.log"
COUNT=0

while read FILE; do
    # printf "checking for $FILE"
    if [[ -e $FILE ]]; then
        # echo "  ...found!  Removing..."
        rm -f "$FILE"
        COUNT=$(( COUNT + 1 ))
    fi
done < $INFILE

echo "$COUNT malware files removed"

8. Thoughts

So yes, some companies may charge you big bucks to scan and clean your WordPress installation. You can do it for free.