Linux Malware Detect (LMD) is a malware scanner for Linux released under the GNU GPLv2 license, that is designed around the threats faced in shared hosted environments. It uses threat data from network edge intrusion detection systems to extract malware that is actively being used in attacks and generates signatures for detection.


In addition, threat data is also derived from user submissions with the LMD checkout feature and from malware community resources. The signatures that LMD uses are MD5 file hashes and HEX pattern matches, they are also easily exported to any number of detection tools such as ClamAV.


Note: This guide assumes you are familiar with SSH and basic command line navigation. These instructions apply primarily to customers who have Virtual Private Servers or Dedicated servers. If you do not have root-level access you will not be able to make these changes.



Installation is very straightforward. Ensure to change the version number below to the one you have actually downloaded:

# cd /usr/local/src
# wget
# tar -zxvf maldetect-current.tar.gz
# cd maldetect-1.4.2
# ./


After the installation has been completed succesfully, you will be presented with the following output.

Linux Malware Detect v1.4.2
            (C) 2002-2011, R-fx Networks 
            (C) 2011, Ryan MacDonald 
inotifywait (C) 2007, Rohan McGovern 
This program may be freely redistributed under the terms of the GNU GPL

installation completed to /usr/local/maldetect
config file: /usr/local/maldetect/conf.maldet
exec file: /usr/local/maldetect/maldet
exec link: /usr/local/sbin/maldet
exec link: /usr/local/sbin/lmd
cron.daily: /etc/cron.daily/maldet

maldet(6073): {sigup} performing signature update check...
maldet(6073): {sigup} local signature set is version 2013102428301
maldet(6073): {sigup} new signature set (2013102428301) available
maldet(6073): {sigup} downloaded
maldet(6073): {sigup} downloaded
maldet(6073): {sigup} downloaded
maldet(6073): {sigup} downloaded
maldet(6073): {sigup} downloaded
maldet(6073): {sigup} signature set update completed
maldet(6073): {sigup} 10849 signatures (8981 MD5 / 1868 HEX)



Maldet can be configured by editing the file below:

# vi /usr/local/maldetect/conf.maldet

The default file looks as follows:

# The default email alert toggle
# [0 = disabled, 1 = enabled]

# The subject line for email alerts
email_subj="maldet alert from $(hostname)"

# The destination addresses for email alerts
# [ values are comma (,) spaced ]

# Ignore e-mail alerts for reports in which all hits have been cleaned.
# This is ideal on very busy servers where cleaned hits can drown out
# other more actionable reports.

# The default quarantine action for malware hits
# [0 = alert only, 1 = move to quarantine & alert]

# Try to clean string based malware injections
# [NOTE: quar_hits=1 required]
# [0 = disabled, 1 = clean]

# The default suspend action for users wih hits
# Cpanel suspend or set shell /bin/false on non-Cpanel
# [NOTE: quar_hits=1 required]
# [0 = disabled, 1 = suspend account]
# minimum userid that can be suspended


You may edit the following values to configure Maldet to your needs

  • email_alert : If you would like to receive email alerts, then it should be set to 1.
  • email_subj : Set your email subject here.
  • email_addr : Add your email address to receive malware alerts.
  • quar_hits : The default quarantine action for malware hits, it should be set 1.
  • quar_clean : Cleaing detected malware injections, must set to 1.
  • quar_susp : The default suspend action for users wih hits, set it as per your requirements.
  • quar_susp_minuid : Minimum userid that can be suspended.


Cronjob for automated scan

During installation, a daily cron job script is installed in /etc/cron.daily/maldet.

The cronjob installed by LMD is used to perform daily update of signature files, keep the session, temp and quarantine data to no more than 14 days old and it runs a daily scan of recent file system changes. If inotify-based real time monitoring is enabled, the daily cron job also scans the recently updated/created files for malware. The folder structures for the most popular control panel configurations: Ensim, Plesk, DirectAdmin, Cpanel, Interworx, have been imcluded.

You should ensure compatibility with your servers’ structure of homedirs and make sure it corresponds with this cron file. Take special note of the control panel specific sections in this cron file.


# clear quarantine/session/tmp data every 14 days
/usr/sbin/tmpwatch 336 /usr/local/maldetect/tmp >> /dev/null 2>&1
/usr/sbin/tmpwatch 336 /usr/local/maldetect/sess >> /dev/null 2>&1
/usr/sbin/tmpwatch 336 /usr/local/maldetect/quarantine >> /dev/null 2>&1
/usr/sbin/tmpwatch 336 /usr/local/maldetect/pub/*/ >> /dev/null 2>&1

# check for new release version
/usr/local/maldetect/maldet -d >> /dev/null 2>&1

# check for new definition set
/usr/local/maldetect/maldet -u >> /dev/null 2>&1

# if were running inotify monitoring, send daily hit summary
if [ "$(ps -A --user root -o "comm" | grep inotifywait)" ]; then
        /usr/local/maldetect/maldet --alert-daily >> /dev/null 2>&1
        # scan the last 2 days of file changes
        if [ -d "/home/virtual" ] && [ -d "/usr/lib/opcenter" ]; then
                # ensim
                /usr/local/maldetect/maldet -b -r /home/virtual/?/fst/var/www/html 2 >> /dev/null 2>&1
                /usr/local/maldetect/maldet -b -r /home/virtual/?/fst/home/?/public_html 2 >> /dev/null 2>&1
        elif [ -d "/etc/psa" ] && [ -d "/var/lib/psa" ]; then
                # psa
                /usr/local/maldetect/maldet -b -r /var/www/vhosts/?/httpdocs 2 >> /dev/null 2>&1
                /usr/local/maldetect/maldet -b -r /var/www/vhosts/?/subdomains/?/httpdocs 2 >> /dev/null 2>&1
        elif [ -d "/usr/local/directadmin" ]; then
                # DirectAdmin
                /usr/local/maldetect/maldet -b -r /var/www/html/?/ 2 >> /dev/null 2>&1
                /usr/local/maldetect/maldet -b -r /home?/?/domains/?/public_html 2 >> /dev/null 2>&1
                # cpanel, interworx and other standard home/user/public_html setups
                /usr/local/maldetect/maldet -b -r /home?/?/public_html 2 >> /dev/null 2>&1

In order to activate email alerts when malware is detected, you need to open the Maldet configuration file, which is located at:
/usr/local/maldetect/conf.maldet .

email_subj="Maldet alert from $(hostname)"


iNotify Monitoring

The inotify monitoring feature is designed to monitor users in real-time for file creation/modify/move operations. This option requires a kernel that supports inotify_watch (CONFIG_INOTIFY) which is found in kernels 2.6.13+ and CentOS/RHEL 5 by default. If you are running CentOS 4 you should consider an inbox upgrade with:

There are three modes that the monitor can be executed with and they relate to what will be monitored, they are USERS|PATHS|FILES.

  • e.g: maldet –monitor users
  • e.g: maldet –monitor /root/monitor_paths
  • e.g: maldet –monitor /home/mike,/home/ashton

The options break down as follows:

  • USERS – The users option will take the homedirs of all system users that are above inotify_minuid and monitor them. If inotify_webdir is set then the users webdir, if it exists, will only be monitored.
  • PATHS – A comma spaced list of paths to monitor
  • FILE – A line spaced file list of paths to monitor

you can run maldet as a daemon as follows. The example below displays the syntax for a comma spaced list of paths to monitor

maldet -m /var,/home
maldet(5330): {mon} set inotify max_user_instances to 128
maldet(5330): {mon} set inotify max_user_watches to 61440
maldet(5330): {mon} added /var to inotify monitoring array
maldet(5330): {mon} added /home/xmodulo to inotify monitoring array
maldet(5330): {mon} starting inotify process on 1 paths, this might take awhile...
maldet(5330): {mon} inotify startup successful (pid: 4154)
maldet(5330): {mon} inotify monitoring log: /usr/local/maldetect/inotify/inotify_log



To scan a folder, for example /home you should enter:

maldet -a /home.

you can examine the malware scan report by running the following command and appending the scan report ID.

maldet --report number-xxxx.xxxxx

To quarantine the infected files, run the following command with the scan report ID. The infected files will then be quarantined for cleaning.

# maldet -q SCAN ID
# maldet –quarantine SCANID

Clean all malware results from a previous scan

# maldet -n SCAN ID
# maldet --clean SCAN ID

Restore a file that you have already quarantined

# maldet -s FILENAME
# maldet --restore FILENAME


Ignore Files

There are three ignore files available in Linux Malware Detect. These can be used to exclude files from daily malware scans.


This is a line spaced file for paths that are to be execluded from search results




This is a line spaced file for signatures that should be removed from file scanning




This is a line spaced file for paths that are to be excluded from inotify monitoring


There may be some situations where you have to move the location of MySQL, for example, if you’re out of disk space or perhaps looking to host it on another device to increase performance. Whatever the reason, moving MySQL is simple and has no impact  on cPanel’s functionality.


1.Create a backup

Please make full database backup(including system tables) before moving your data directory. This action will prevent data losing in case if something goes wrong.

# tar -cvf mysql.tar /var/lib/mysql

2.Edit the my.cnf file

# vi /etc/my.cnf

Now in the mysqld section add the following. Don’t restart MySQL after adding new entry.


3.Create the new MySQL data directory

# mkdir /home/mysql

4.Now migrate the data to the new location using rsync command.

# nohup rsync -avp /var/lib/mysql/ /home/mysql

The nohup will keep rsync running even when your session with the server end, the other part “

# tail -f nohup.out

Notice that you have to do the syncing process twice because when moving large size of data can take some time to complete and the tables may have changed in between. When we run it the second time we hopefully get it so that when the switch over happens there is very little, if any, lost data. If you can afford the downtime simply shut down MySQL before running this command.If you cannot though running it twice then quickly copy/pasting the other commands is a valid substitute.

5.Typically you want to stop MySQL for syncing data completely.

# /etc/init.d/mysqld stop

6.Start the re-sync process once again to copy data’s completely.

# rsync -avp --delete /var/lib/mysql/ /home/mysql/

7. Change ownership of new created MySQL data directory to MySQL.

# chown -R mysql:mysql /home/mysql/

8. Now, re-link the socket file to /tmp:

# rm -rf /tmp/mysql.sock
# ln -sf /home/mysql/mysql.sock /tmp/mysql.sock

9. Since you already added the data directory entry to my.cnf , all you need to do is restart again and everything should be working.

# /etc/init.d/mysqld start

Check whether your MySQL logs are written at the new location (Eg: /home/mysql/hostname.err)

10. Create a sample database named “test” for checking.

# mysqladmin create test

11. Check whether the new database is created at new data directory.

# ls -d /home/mysql/test

12. After confirming everything works properly.You can remove the old data directory.

# rm -rf  /var/lib/mysql

Is it possible?

Yeah, definitely! You can create a complete cPanel account backup by excluding the home directory. This is very important, because, if the home directory of cPanel accounts have a large amount of data, this will increase the total time for the account migration.

Generating backup and restoring it for a large account is the much time-consuming process. If you need a faster solution, exclude the home directory then complete the account migration without its home directory. After that start syncing the home directory from source to destination server 🙂

cPanel provides necessary scripts to do this kind of operations via server CLI (command line interface). Here I am listing those scripts for account migration.

Command to create a cPanel backup file


Package account.

Important cPanel scripts

How to create cPanel backup without its home directory?

/scripts/pkgacct --skiphomedir user

Replace user with cPanel user name.

The cPanel script to restore an account is pasted below:

/scripts/restorepkg $

I guess you all are familiar with those scripts. Here we go!!

This is a simple for loop to generate backups, sync that to remote host and remove that backup file from the source server after syncing them to remote host.

Here is the script for doing so:

for x in `\ls -A1 /var/cpanel/users/`; do /scripts/pkgacct --skiphomedir ${x} ; rsync -aP /home/cpmove-${x}.tar.gz -e ssh root@destination.server:/home/ ; rm -f /home/cpmove-${x}.tar.gz ; done

Replace destination.server with the IP address of destination server.

If you want to maintain those backups on the source server, remove the last entry.

for x in `\ls -A1 /var/cpanel/users/`; do /scripts/pkgacct --skiphomedir ${x} ; rsync -aP /home/cpmove-${x}.tar.gz -e ssh root@NEW-SERVER-IP:/home/ ; done

Yeah, you have successfully created backup files and synced those files to the remote server. Now you need to restore those backups to the destination server.

Execute the following command on destination server.

for x in `ls -A1 /home/cpmove*` ; do /scripts/restorepkg /home/${x} ; done

That’s it!!!

Wait wait, where is home directories? Yeah you need to sync home directories to destination server. Syncing directories is not a big task. Please execute the following command:

rsync -aP /home/ -e ssh root@destination.server:/home/

Rsync commands in details

Yup! You’ve successfully completed the account migration.
Change the name servers of those domains to load it from the new server.

This can be done by executing the “whmapi1” command via Linux Shell. WHM API 1 accesses the WHM interface’s features. You can use this API to perform server administration tasks, administrate cPanel and WHM reseller accounts, and manage cPanel & WHM services.

You can create a temporary root WHM session by executing the following command:

bash-4.1# whmapi1 create_user_session user=root service=whostmgrd

  cp_security_token: /cpsess3485551384
  expires: ‘1492600874’
  service: whostmgrd
  session: root:b8AC4rvpcYcKo5YF:create_user_session,90f2017bccccd915920e051c2960a3d6
  command: create_user_session
  reason: Created session
  result: 1
  version: 1

This is a one-time-use session to access WHM panel. Just copy the WHM URL and paste it on web browser. This link will bypass the need to enter a root password. That’s it!


Whmapi command to create a WHM session for reseller account

To create a WHM session for a reseller account, just change the “user” name from root to reseller account’s user name. That’s it!

Same you can login to the cPanel without password by using following command:

whmapi1 create_user_session user=USER_NAME service=cpaneld


Plesk is not accessible. The error below is shown:

ERROR: PleskFatalException
Unable to connect to database: Unknown database 'psa'

0: common_func.php3:150
    psaerror(string 'Unable to connect to database: Unknown database 'psa'')
1: auth.php3:111


The psa database does not exist.


  1. Log in to MySQL and check if the psa database exists:
    # MYSQL_PWD=`cat /etc/psa/.psa.shadow` mysql -u admin
    mysql> show databases like 'psa';
    Empty set (0.00 sec)

    So, at this point, you need to restore the database from the latest available backup on the server.

  2. Check if backups exist in the dump directory:
    ~# grep dump /etc/psa/psa.conf
    DUMP_D /var/lib/psa/dumps
    ~# ls -la  # ls -lt /var/lib/psa/dumps/mysql.daily.dump*
    -rw------- 1 root root 239658 Dec 10 03:37 /var/lib/psa/dumps/mysql.daily.dump.0.gz
    -rw------- 1 root root 241242 Dec  9 03:37 /var/lib/psa/dumps/mysql.daily.dump.1.gz
    -rw------- 1 root root 241376 Dec  8 03:37 /var/lib/psa/dumps/mysql.daily.dump.2.gz
    -rw------- 1 root root 241887 Dec  7 03:38 /var/lib/psa/dumps/mysql.daily.dump.3.gz
    -rw------- 1 root root 237143 Dec  6 03:38 /var/lib/psa/dumps/mysql.daily.dump.4.gz
    -rw------- 1 root root 233966 Dec  5 03:36 /var/lib/psa/dumps/mysql.daily.dump.5.gz
    -rw------- 1 root root 233495 Dec  4 03:38 /var/lib/psa/dumps/mysql.daily.dump.6.gz
    -rw------- 1 root root 232856 Dec  3 03:36 /var/lib/psa/dumps/mysql.daily.dump.7.gz
    -rw------- 1 root root 232710 Dec  2 03:36 /var/lib/psa/dumps/mysql.daily.dump.8.gz
  3. Restore the latest daily dump (from Dec. 10 in this case) using the commands below:
    # gunzip /var/lib/psa/dumps/mysql.daily.dump.0.gz 
    # MYSQL_PWD=`cat /etc/psa/.psa.shadow` mysql -u admin  -e "create database psa"
    # MYSQL_PWD=`cat /etc/psa/.psa.shadow` mysql -u admin psa < /var/lib/psa/dumps/mysql.daily.dump.0

Custom php.ini file with FastCGI

Posted: December 15, 2016 in other

  1. Login to your server via SSH.
  2. Make a backup copy of your cPanel PHP wrapper script with the following command:

    cp -frp /usr/local/cpanel/cgi-sys/php5 /usr/local/cpanel/cgi-sys/php5-BACKUP

  3. Now edit the cPanel PHP wrapper script with your favorite text editor:

    vi /usr/local/cpanel/cgi-sys/php5

    By default this script should look like:


    # If you customize the contents of this wrapper script, place
    # a copy at /var/cpanel/conf/apache/wrappers/php5
    # so that it will be reinstalled when Apache is updated or the
    # PHP handler configuration is changed

    exec /usr/bin/php

  4. Above the line exec /usr/bin/php add the following code:

    [[ -f ~/public_html/php.ini ]] && exec /usr/bin/php -c ~/public_html/php.ini

    Now the cPanel PHP wrapper script should look like:


    # If you customize the contents of this wrapper script, place
    # a copy at /var/cpanel/conf/apache/wrappers/php5
    # so that it will be reinstalled when Apache is updated or the
    # PHP handler configuration is changed

    [[ -f ~/public_html/php.ini ]] && exec /usr/bin/php -c ~/public_html/php.ini
    exec /usr/bin/php

    What this does is uses the Bash syntax for seeing if a file exists [[ -f ]] and in this case we’re looking for the file ~/public_html/php.ini. The ~ symbol would represent the current user calling the script, so this would be the same as entering in either /home/user1/public_html/php.ini or /home/user2/public_html/php.ini as the full path.

    The rest of the code simply executes the PHP binary at /usr/bin/php with the -c flag which sets the location where you’d like to load a php.ini from from. In this case we are telling the server we’d like to use the php.ini file inside the user’s /public_html/ directory if one exists, instead of /usr/local/lib/php.ini which would be the server’s default.

  5. Now you’ll want to copy the cPanel PHP wrapper script to a more permanent location, so that your settings are saved if you ever recompile Apache down the road. This can be done using the following command:

    mkdir -p /var/cpanel/conf/apache/wrappers
    cp -frp /usr/local/cpanel/cgi-sys/php5 /var/cpanel/conf/apache/wrappers/php5

  6. Now restart Apache for the settings to become active:

    service httpd restart

  7. In order to verify your settings have been applied you’ll want to create a PHP info script, the simplest way of doing this is simply copying any of your files to a file such as info.php, and then overwriting it with the phpinfo(); function:

    echo ‘<?php phpinfo(); ?>’ > ~user1/public_html/info.php

    Now when you visit your website and access the newly crated info.php script, you should see your custom php.ini being loaded next to the Loaded Configuration File section

Common paths in cPanel and WHM

Posted: December 9, 2016 in Cpanel

For those users who use cPanel/WHM on their virtual or dedicated servers the following article describes common system paths and utilities.

Paths of Base Modules



/usr/local/bin/convert or /usr/bin/convert




Ruby Gems




FLV Tool

User Directories
Document Root

WWW Directory

CGI Directory

cPanel / WHM Core Directories and Files
Houses only scripts and binaries which provide installation and configuration of many cPanel services.

Houses proprietary configuration data for cPanel, including:

Primary cPanel configuration
User configurations
Reseller configurations
Accounting, conversion, and update logs
Bandwidth data
Customized service templates

The primary cPanel configuration file. Each variable within influences the way cPanel behaves, variables are line delimited, with variables separated by an equal sign. If this file does not exist cPanel falls back to defaults.

Lists each reseller with a comma-delimited list of WHM resources that reseller has access to.

Contains a list of accounting functions performed through WHM, including account removal and creation.

Files contain a list of bandwidth history for each account, each named after their respective user. History files are stored in human-readable format, while actual bandwidth data are stored in round robin databases.

File name is inherited from the feature list name. Contains a line delimited list of feature variables and a zero or one value. Variables control what cPanel resources are available to users.

Contains a list of packages named after the packages they represent. If a package belongs to reseller file name is prefixed with reseller username. Each of these values determines the value created in cPanel user file.

Contains a list of cPanel user configuration files named after the user they pertain to. Variables define account resources, themes, domains, etc.

Other /var/cpanel Directories
This directory contains logs from account copies/transfers.

Contains the output of each cPanel update executed on the server.

Named after the respective reseller users they represent, each contains only the IP address which should be used as resellers main shared IP.

Contains customized DNS zone templates created in WHM.

This directory houses a large number of scripts which serve as building blocks for many cPanel/WHM features.
These scripts can be used to:

Update cPanel and many of its services
Customize account creation routines
Perform backups of cPanel accounts
Install and update cPanel managed services

cPanel Maintenance Scripts
By default cPanel applies nightly updates at 2:13AM server time via the root crontab.
/scripts/upcp dispatches these updates using the following key components:

/scripts/updatenow – synchronizes /scripts directory
/scripts/sysup – updates cPanel managed rpms
/scripts/rpmup – updates all other system updates
Updates are logged to timestamped files in /var/cpanel/updatelogs. Update configuration is stored in /etc/cpupdate.conf

Account Management Scripts
/scripts/wwwacct (account creation)
/scripts/killacct (account termination)
/scripts/suspendacct (account suspension)
/scripts/unsuspendacct (account resuming)
/scripts/addpop (create pop account)
Updates the user:owner and user:domain tables stored in:
These tables are used to enumerate and keep track of accounts and their owners.

Package Management
Takes argument list of rpms, which are then passed to the underlying package manager.

The equivalent of ensurerpm for FreeBSD. Updates specified packages from ports.

Takes argument list of perl modules to install via CPAN. Each of the aforementioned scripts can accept an argument of ‘–force’ to force package installations.

Can be called to apply MySQL updates independent of upcp.

Will clean up the default MySQL privilege tables, by installing a more restrictive privilege schema.

Will verify that mysql is accessible with password stored in /root/.my.cnf and force a reset with a random 16 character string if inaccessible.

Can be called to apply exim updates independent of upcp.

Will rebuild exim.conf, and merge local, distribution, and cPanel configurations.

Rebuild named.conf based on existing zone files

Download, extract, and execute apache build script

Rebuilds httpd.conf based on DNS entries found in each cPanel user configuration

Other cPanel Scripts
The majority of cPanel managed service can be scripts named appropriately.

Will rebuild the PHP interpreter used internally by cpsrvd.

Will scan for and install any Perl modules required by cPanel.

Updates horde and resets the horde mysql user password.

Will attempt to rebuild quota database per information stored in /etc/quota.conf