Scan for Malware with ISPProtect

The ISPProtect Malware scanner does not have to be installed, it can be downloaded to e.g. /tmp and used right away. If you want to use the scanner regularly on this server, then please see installation chapter.

Login as root user on the shell of your server and download ISPProtect with wget to the /tmp directory of your server and unpack the tar.gz file.

cd /tmp
wget https://www.ispprotect.com/download/ispp_scan.tar.gz
tar xzf ispp_scan.tar.gz

Start the scan process:

./ispp_scan

In a first step, the scanner checks if the system requirements are fulfilled. ISPProtect requires PHP (version between 5.2 – 7.0) and ClamAV.

ispp_scan_1

Enter your ISPProtect license key or the word „TRIAL“ if you have no license key yet and just want to test ISPProtect.

Please enter scan key (or TRIAL if you have none, yet): ← TRIAL

Now the program will ask for the path to be scanned. This is the directory where the websites are stored on your server. In most cases, this will be /var/www or /srv/www for OpenSuSE.

Please enter path to scan: ← /var/www

ispp_scan_2

The scan begins. The Scanner will show the results on the screen and saves the scan result also in the files listed above. The scan progress and estimated scan time is shown.

The scan consists of 3 scan levels. In the first level, the system will be scanned with the signature based scanner, the second scan is a heuristic scan for malware and the third scan scans for outdated cms system versions.

Here is the full output of an ISPProtect scan.

./ispp_scan
       _____  _____ _____  _____           _            _
      |_   _|/ ____|  __ \|  __ \         | |          | |
        | | | (___ | |__) | |__) | __ ___ | |_ ___  ___| |_
        | |  \___ \|  ___/|  ___/ '__/ _ \| __/ _ \/ __| __|
       _| |_ ____) | |    | |   | | | (_) | ||  __/ (__| |_
      |_____|_____/|_|    |_|   |_|  \___/ \__\___|\___|\__|
 __          __  _        _____
 \ \        / / | |      / ____|
  \ \  /\  / /__| |__   | (___   ___ __ _ _ __  _ __   ___ _ __
   \ \/  \/ / _ \ '_ \   \___ \ / __/ _` | '_ \| '_ \ / _ \ '__|
    \  /\  /  __/ |_) |  ____) | (_| (_| | | | | | | |  __/ |
     \/  \/ \___|_.__/  |_____/ \___\__,_|_| |_|_| |_|\___|_|

                                               Version 1.6.1

                    (c) 2015 by ISPConfig UG
                       all rights reserved


Downloading ionCube Loader for your system.
ionCube Check succeeded.
Please enter scan key (or TRIAL if you have none, yet): TRIAL
Please enter path to scan: /var/www
Starting malware scan.
This can take a long, long time depending on the server hardware and the amount of files ...

!!! DO NOT INTERRUPT THE SCRIPT !!!!

After the scan is completed, you will find the results also in the following files:
Malware => /tmp/found_malware_20152911154431.txt
Wordpress       => /tmp/software_wordpress_20152911154431.txt
Joomla  => /tmp/software_joomla_20152911154431.txt
Drupal  => /tmp/software_drupal_20152911154431.txt
Mediawiki       => /tmp/software_mediawiki_20152911154431.txt
Plugins => /tmp/plugins_20152911154431.txt
Starting scan level 1 ...
Scanning 82044 files now ...
Scan level 1 completed. 3 hits.
Starting scan level 2 ...
Scanning 32233 files now ...
Scan level 2 completed. 2 hits.
================================
Found 5 malware file(s)
================================
Malware suspect.globals.eval in /var/www/clients/client16/web30/web/include/resource/post.php
Malware suspect.post.eval in /var/www/clients/client4/web2/web/wiki.php
Malware {HEX}r2h.malware.blue.13 in /var/www/clients/client5/web18/web/webtools_forum/mod.php
Malware {HEX}php.exe.globals.400 in /var/www/clients/client8/web24/web/blog/maintenance/gen.php
Malware winnow.malware.vx.url.929756 in /var/www/webalizer/usage_201509.html
================================
Starting WordPress check. This could take a while ...
Most decent version(s): 4.3.1
Outdated wordpress version: 2.2.2 (newest is 4.3.1) in "/var/www/clients/client9/web2/web"
Outdated wordpress version: 2.2.1 (newest is 4.3.1) in "/var/www/clients/client8/web3/web"
Outdated wordpress version: 2.7.1 (newest is 4.3.1) in "/var/www/clients/client4/web7/web"
Outdated wordpress version: 2.6 (newest is 4.3.1) in "/var/www/clients/client17/web33/web"
Outdated wordpress version: 3.6 (newest is 4.3.1) in "/var/www/clients/client5/web17/web/website"
Outdated wordpress version: 3.5.1 (newest is 4.3.1) in "/var/www/clients/client5/web17/web/old/website"
Outdated wordpress version: 2.8 (newest is 4.3.1) in "/var/www/clients/client22/web39/web"
Outdated wordpress version: 2.8.1 (newest is 4.3.1) in "/var/www/clients/client22/web39/web/wp-content/upgrade/wordpress-2.8.1/wordpress"
Outdated wordpress version: 3.2.1 (newest is 4.3.1) in "/var/www/clients/client10/web25/web"
Outdated wordpress version: 3.0.1 (newest is 4.3.1) in "/var/www/clients/client21/web38/web"
Outdated wordpress version: 3.1 (newest is 4.3.1) in "/var/www/clients/client21/web38/web/wp-content/upgrade/wordpress-3.tmp/wordpress"
Outdated wordpress version: 3.0.1 (newest is 4.3.1) in "/var/www/clients/client21/web38/web/wp-content/upgrade/core/wordpress"
Wordpress check found 0 current and 12 outdated versions.
================================
Starting Joomla check. This could take a while ...
Most decent version(s): 2.5.28, 3.1.3, 3.2.7, 3.4.5
Joomla check found 0 current and 0 outdated versions.
================================
Starting Drupal check. This could take a while ...
Most decent version(s): 8.0.0, 7.41, 6.37
Drupal check found 0 current and 0 outdated versions.
================================
Starting Mediawiki check. This could take a while ...
Most decent version(s): 1.26.0
Outdated mediawiki version: 1.9.3 (newest is 1.26.0) in "/var/www/clients/client8/web9/web/wiki"
Outdated mediawiki version: 1.14.0 (newest is 1.26.0) in "/var/www/clients/client2/web6/web/disabled_9841"
Mediawiki check found 0 current and 2 outdated versions.
================================
Wordpress plugin All In One SEO V1.4.7 in /var/www/clients/client9/web2/web/ is vulnerable to Privilege escalation

 

Install ISPProtect

ISPProtect can be used without installation as outlined in the first chapter. If you like to use ISPProtect regularily, then follow the instructions below to install it permanently on your server.

Login as root user on the shell of your server. Create the installation directory for ISPProtect, I will use /usr/local/ispprotect here:

mkdir -p /usr/local/ispprotect
chown -R root:root /usr/local/ispprotect
chmod -R 750 /usr/local/ispprotect
cd /usr/local/ispprotect
wget https://www.ispprotect.com/download/ispp_scan.tar.gz
tar xzf ispp_scan.tar.gz
rm -f ispp_scan.tar.gz
ln -s /usr/local/ispprotect/ispp_scan /usr/local/bin/ispp_scan

Now you can start ISPProtect with the command:

ispp_scan

without entering the installation directory first.

 

Update ISPProtect

Run the ispp_scan command, it will notify you when there is a newer version of the scan engine available and will download the update automatically after your approval. The Malware signatures are always updated automatically when you scan your server.

 

Report Malware

ISPProtect contains a built-in malware reporting tool. If you found malware on your server that had not been detected by ISPProtect, then please report it with the following command:

./ispp_scan --report=/path/to/the/malware/file.php

ISPProtect will ask for your approval, before it sends the malware file to our servers. Please do not send files that contain passwords or other sensitive data. Our security researchers will review the reported file (this takes normally 1-2 days) and add a malware signature for it in ISPProtect.

Example:

root@web:/tmp# ./ispp_scan --report=/var/www/web1/tool1.php
       _____  _____ _____  _____           _            _
      |_   _|/ ____|  __ \|  __ \         | |          | |
        | | | (___ | |__) | |__) | __ ___ | |_ ___  ___| |_
        | |  \___ \|  ___/|  ___/ '__/ _ \| __/ _ \/ __| __|
       _| |_ ____) | |    | |   | | | (_) | ||  __/ (__| |_
      |_____|_____/|_|    |_|   |_|  \___/ \__\___|\___|\__|
 __          __  _        _____
 \ \        / / | |      / ____|
  \ \  /\  / /__| |__   | (___   ___ __ _ _ __  _ __   ___ _ __
   \ \/  \/ / _ \ '_ \   \___ \ / __/ _` | '_ \| '_ \ / _ \ '__|
    \  /\  /  __/ |_) |  ____) | (_| (_| | | | | | | |  __/ |
     \/  \/ \___|_.__/  |_____/ \___\__,_|_| |_|_| |_|\___|_|

                                               Version 1.6.1

                    (c) 2015 by ISPConfig UG
                       all rights reserved


ionCube Check succeeded.
Please note that the FULL file is sent to the ISPProtect server.
We will delete all files after investigation but you should NOT SEND files containing LOGIN DATA etc.
Please confirm that you want to send tool1.php (y/N):<- y
Thank you. We have received your report and will check the file.
Be aware that we cannot reply to your report.

 

Report false positives

ISPProtect contains a built-in false positive reporting tool. If ISPProtect listed a file as malware which is not a malicious file, then please report it with the following command:

./ispp_scan --false-positive=/path/to/the/malware/file.php

ISPProtect will ask for your approval before it sends the file to our servers. Please do not send files that contain passwords or other sensitive data. Our security researchers will review the reported file (this takes normally 1-2 days) and add a whitelist signature for it in ISPProtect.

In case the reported file is a HTML file that was generated by a website statistics tool like Webalizer or AWStats that shows the access to a malware in the statistics, then please do not report this HTML file as a false positive.

 

Remove ISPProtect

ISPProtect does not install any software on your server. All you have to do to remove ISPProtect is to delete the ispp_scan* files in the folder where you downloaded ISPProtect.

 

Run ISPProtect in incremental mode

When run as a cron job you might want to do a full scan only once a week or month. In that case you can run a daily scan that just scans files created or modified within the last two (or X) days. Just add --max-age=2 to the argument list for the ispp_scan call and the scanner will skip all files older than 2 (or X) days. Keep in mind that those file dates could be faked, so you should always do a full scan at least once a month.

 

Exclude files from scan

To exclude some files or paths from scan you can use the --exclude and --exclude-from arguments, e. g. to exclude all PNG files, type --exclude="*.png" (case-sensitive)
To exclude a log directory, e. g. in ISPConfig websites use --exclude="**/log/*.log"
--exclude can be used multiple times but it might be more convenient putting all the exclude patterns in one file line by line (e. g. /usr/local/ispprotect/excludes.list) and provide --exclude-from=/usr/local/ispprotect/excludes.list or whatever path you chose.

 

Local whitelisting

ISPProtect allows you to create a local whitelist. You can add a file to the whitelist by calling

ispp_scan --whitelist=/path/to/your/file.php

With this a md5 hash of the file is added to the whitelist so every other file with the same content is excluded from further hits.

By default the whitelist is stored in ~/.ispp_scan.whitelist
You can change this path by adding the whitelist-path argument:

ispp_scan --whitelist-path=/home/user/.ispprotect.wl --whitelist=/path/to/your/file.php

You can use the whitelist-path argument on your scans to use the custom whitelist location on your scan runs.

 

Ignoring malware types

You can ignore specific malware types by using the ignore argument, e. g.:

ispp_scan --ignore={ISPP}suspect.eval.base64

This would ignore all malware named {ISPP}suspect.eval.base64 (not recommended, of course). You can use this argument multiple times to ignore more than one malware type.

 

Run ISPProtect as Cronjob

Create a cronjob file to run ISPProtect automatically once a day, week or month on your server as outlined below. I assume that you installed ISPProtect in the /usr/local/ispprotect folder.

nano /etc/cron.d/ispprotect

with the following content:

#
#  ISPProtect cronjob
#
# Minute   Hour   Day of Month       Month          Day of Week        User Command    
# (0-59)  (0-23)     (1-31)    (1-12 or Jan-Dec)  (0-6 or Sun-Sat)    


# Daily ISPProtect cronjob
# 0 3  * * *   root	/usr/local/ispprotect/ispp_scan --update && /usr/local/ispprotect/ispp_scan --path=/var/www --email-results=root@localhost --non-interactive --scan-key=AAA-BBB-CCC-DDD

# Daily incremental ISPProtect cronjob
# 0 3  * * *   root	/usr/local/ispprotect/ispp_scan --update && /usr/local/ispprotect/ispp_scan --no-version-scan --path=/var/www --email-results=root@localhost --non-interactive --max-age=2 --scan-key=AAA-BBB-CCC-DDD

# Weekly ISPProtect cronjob run on sunday
# 0 3  * * 0   root	/usr/local/ispprotect/ispp_scan --update && /usr/local/ispprotect/ispp_scan --path=/var/www --email-results=root@localhost --non-interactive --scan-key=AAA-BBB-CCC-DDD

# Monthly ISPProtect cronjob
# 0 3  1 * *   root	/usr/local/ispprotect/ispp_scan --update && /usr/local/ispprotect/ispp_scan --path=/var/www --email-results=root@localhost --non-interactive --scan-key=AAA-BBB-CCC-DDD

How to adjust the cron file:

1) Remove the # in front of one of the 4 cron command lines to activate it.
2) Replace /var/www with the path that shall be scanned.
3) Replace root@localhost with your email address. The Scan report will be sent to this address.
4) Replace AAA-BBB-CCC-DDD with your ISPProtect license key.

WARNING! Plesk servers

If you are using ISPProtect on a plesk server, the scanning won't work via cron job by default. Please add the following to your /etc/cron.d/ispprotect cron file right at the top (or change the existing PATH value):

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

In addition you should add

 >/dev/null 2>&1

to each cron command line to prevent being "spammed" by cron emails.

 

Deploy ISPProtect with Puppet

Puppet can be used for automatic deployment of ISPProtect in larger server farms. The ISPProtect Puppet module developed by Eelco Maljaars can be found here at Puppet Forge:

https://forge.puppet.com/eelcomaljaars/ispprotect

The source code is also available at GitHub.

https://github.com/eelcomaljaars/puppet_ispprotect/

 

Advanced Options

Run the command:

./ispp_scan --help

to get a list of all available options of the ispp_scan command.

ispp_scan --help
       _____  _____ _____  _____           _            _
      |_   _|/ ____|  __ \|  __ \         | |          | |
        | | | (___ | |__) | |__) | __ ___ | |_ ___  ___| |_
        | |  \___ \|  ___/|  ___/ '__/ _ \| __/ _ \/ __| __|
       _| |_ ____) | |    | |   | | | (_) | ||  __/ (__| |_
      |_____|_____/|_|    |_|   |_|  \___/ \__\___|\___|\__|
 __          __  _        _____
 \ \        / / | |      / ____|
  \ \  /\  / /__| |__   | (___   ___ __ _ _ __  _ __   ___ _ __
   \ \/  \/ / _ \ '_ \   \___ \ / __/ _` | '_ \| '_ \ / _ \ '__|
    \  /\  /  __/ |_) |  ____) | (_| (_| | | | | | | |  __/ |
     \/  \/ \___|_.__/  |_____/ \___\__,_|_| |_|_| |_|\___|_|

                                              Version 1.24.14

                 (c) 2015-2018 by ISPConfig UG
                       all rights reserved


ionCube Check succeeded.

Usage instructions:
Call ./ispp_scan [--path=] [--no-version-scan] [--no-malware-scan] [--exclude=] [--exclude-from=] [--ignore-chmod0] [--no-plugin-version-scan] [--email-results=,,... [--email-empty-results]] [--non-interactive] [--quarantine[=xxxxxx] [--all|--restore]] [--scan-key=] [--whitelist-path=] [--max-age=] [--incremental[=all]] [--show-hits] [--ignore=] [--use-tmp=] [--db-scan[=]] [--db-scan-maxrows] [--blacklist-check]
or
Call ./ispp_scan --key-status [--scan-key=]
or
Call ./ispp_scan --update [--email-results=,,...]
or
Call ./ispp_scan --report= [--email=]
or
Call ./ispp_scan --false-positive= [--force-yes] [--email=]
or
Call ./ispp_scan --whitelist= [--whitelist-path=]

        --path                  What path should be scanned for malware? If not given, path is asked on script run.
        --no-malware-scan       Don't scan for malware.
        --no-version-scan       Don't scan for outdated web software (this implies --no-plugin-version-scan).
        --no-plugin-version-scan        Don't Scan for outdated wordpress plugins.
        --no-dereference        Don't resolve symlinks in paths found having outdated software versions.
        --no-symlinks           Don't follow symlinks in typo3 check. ONLY use if you have issues with scan.
        --email-results         Send found malware and outdated software to the provided address(es).
        --email-results-sender  Set the sender address for your report emails.
        --email-empty-results   Send scan report to email even if no malware was found.
        --email-hostname        Use this hostname for email reports instead of guessing it.
        --use-smtp              Use smtp mail sending instead of internal mail() function.
                                You need to provide a configuration file with smtp settings, i. e. --use-smtp=/path/to/ispp_mail.cnf
                                The file must be of the following form:
                                [ispprotect-smtp]
                                use_smtp = yes
                                smtp_host = mail.yourdomain.com
                                smtp_port = 25
                                smtp_user = yoursmtpusername
                                smtp_pass = yoursmtppassword
                                smtp_crypt = ssl

                                Instead of ssl you can choose tls as encryption mode.
        --non-interactive       Do not ask for input. You need to provide --scan-key to use non-interactive mode. Automatic updates are disabled.
        --ignore                Malware of this type is not included in results (case-insensitive), e.g. --ignore={ISPP}suspect.eval.base64
                                Can be used multiple times.
        --exclude               You can specify patterns to exclude from files to scan, e. g. --exclude='*.png' to ignore all png files.
                                * is a placeholder for all characters except /. Do exclude full paths, use **, e. g. --exclude='**/log/*.log'
                                Can be used multiple times.
        --exclude-from          To avoid having to specify --exclude many times you can use --exclude-from pointing to a file
                                that contains multiple exclude patterns (same form as for --exclude), one line each.
                                Can be used multiple times.
        --quarantine            Move infected files to quarantine directory.
        --quarantine=YYYYMMDDHHMMSS     Move infected files from a finished run to quarantine directory.
        --all                   Also move possibly malicious files to quarantine directory (higher risk of false positives being moved).
        --restore               Restore all quarantined files of a scan.
        --whitelist             File will be added to the local whitelist.
        --whitelist-path        Path to the hash file for the whitelist. Default is ~/.ispp_scan.whitelist
        --key-status            Check status of provided key (e. g. amount of scans left).
        --scan-key              Provide your scan key for non-interactive mode or the path to the file containing your scan key.
        --show-hits             Show found malware files during scan (you will lose the progress output).
        --max-age               Scan only files newer than X days.
        --ignore-chmod0 This option ignores all files that have a chmod of 000 during scan.
        --incremental           Only check files at level 2 that have not been previously scanned as 'clean'.
        --time-check            Check files for possibly faked modification times.
                                This feature is only available on some file systems and is known to throw a lot of false positives.
                                You should only use this for diagnostic purposes.
                                If no signature file is found or it was created by a previous ISPProtect version, a full run is done.
                                If using --incremental the --max-age argument is NOT taken into account for scan level 2!
                                If used with --incremental=all found malware files will not be scanned again on next run, too.
        --update                Update ISPProtect silently and quit. Return code will be 0 on success, 1 otherwise.
        --report                Send a file to ISPProtect server that was accidently not recognized as malware.
        --false-positive        Send a file to ISPProtect server that was accidently recognized as malware.
        --force-yes             Do not ask for confirmation before sending a false positive file to the ISPProtect server.
        --use-tmp               If your /tmp directory has not enough space or is not usable, you can specify an alternative path here.

        --db-scan               This feature will scan your (local) databases for suspect contents.
                                This feature is still in *experimental* state, but it can't do any harm to use it.
                                On Debian-based servers it should be enough to use --db-scan because the tool uses the credentials from
                                the /etc/mysql/debian.cnf config file. On servers that don't have this file, you have to create your own
                                and provide the path, e. g. --db-scan="/root/myisppdatabase.cnf"
                                The file's contents should look like this:
                                [ispprotect]
                                user = yourmysqluser
                                password = yourmysqlpassword
                                host = yourmysqlhost
                                The "host" entry is optional, default is "localhost". Please make sure that the config file is not
                                readable by unprivileged users!
                                For security reasons you can create a special database user that has read-only privileges.
        --db-scan-maxrows       By default the tool scans up to 1.000.000 rows per database table. Your can set this value
                                to a lower one, e. g. --db-scan-maxrows=10000
                                If you want to scan ALL rows (not recommended) you can set --db-scan-maxrows=0
        --db-no-context         Do not display the context of found strings in databases
        --db-exclude            Do not scan databases matching the string, wildcards supported (? = single char, * = any substring)
        --db-exclude-table      Do not scan tables matching the string, wildcards supported (? = single char, * = any substring)
        --db-only               Do ONLY scan databases matching the string, wildcards supported (? = single char, * = any substring)
        --db-only-table         Do ONLY scan tables matching the string, wildcards supported (? = single char, * = any substring)
                                these four arguments can be used multiple times to exclude / only scan multiple dbs/tables
        --blacklist-check       The scanner tries to extract your set up domains from /etc (Apache / Nginx for now)
                                and sends the domain names to different third party sites.
                                If those services return matches for any of the domains, those are presented by ISPProtect.