Linux Malware Detect for occasional non-root use

This post was written by eli on December 31, 2015
Posted Under: Drupal,Linux,Server admin,Software

Intro

This is a minimal HOWTO on installing Linux Malware Detect for occasional use as a regular non-root user. Not that I’m so sure it’s worth bothering, given that contemporary exploit code seems to be able to go under its radar.

Background

One not-so-bright afternoon, I got a sudden mail from my web hosting provider saying that my account has been shut down immediately due to malware detected in my files (citation is slightly censored):

Hello,
Our routine malware scanner has reported files on your account as malicious. Pasted below is the report for your confirmation. Your account hosts old, outdated and insecure scripts which needs to be updated asap. Please reply back to this email so that we can work this out.

====================================
HOST: ——-
SCAN ID: 151230-0408.31792
STARTED: Dec 30 2015 04:08:40 -0500
TOTAL HITS: 1
TOTAL CLEANED: 0

FILE HIT LIST:
{HEX}php.base64.v23au.185 : /home/——/public_html/modules/toolbar/javascript21.php => /usr/local/maldetect/quarantine/javascript21.php.295615562
===============================================

I was lucky enough to have a backup of my entire hosted subdirectory, so I made a new backup, ran

$ find . -type f | while read i ; do sha1sum "$i" ; done > ../now-sha1.txt

on the good and bad, and then compared the output files. This required some manual cleanup of several new PHP files which contained all kind of weird stuff.

In hindsight, it seems like the malware PHP files were created during an SQL injection attack on Drupal 7 back in October 2014 (read again: an SQL injection attack in 2014. It’s as if a malaria breakout would occur in Europe today). The web host did patch the relevant file for me (without me knowing about it, actually), but only a couple of days after the attack broke loose. Then the files remained undetected for about a year, after which only one of these was nailed down. The malware PHP code is clearly crafted to be random, so it works around pattern detection.

Now, when we’re convinced that Linux Malware Detect actually doesn’t find malware, let’s install it.

Installing

There are plenty of guides on the web. Here’s my own take.

$ git clone https://github.com/rfxn/linux-malware-detect.git

For those curious on which revision I’m using:

$ git rev-parse HEAD
190f56e8704213fab233a5ac62820aea02a055b2

Change directory to linux-malware-detect/, and as root:

# ./install.sh
Linux Malware Detect v1.5
            (C) 2002-2015, R-fx Networks <proj@r-fx.org>
            (C) 2015, Ryan MacDonald <ryan@r-fx.org>
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(15488): {sigup} performing signature update check...
maldet(15488): {sigup} could not determine signature version
maldet(15488): {sigup} signature files missing or corrupted, forcing update...
maldet(15488): {sigup} new signature set (2015121610247) available
maldet(15488): {sigup} downloading http://cdn.rfxn.com/downloads/maldet-sigpack.tgz
maldet(15488): {sigup} downloading http://cdn.rfxn.com/downloads/maldet-cleanv2.tgz
maldet(15488): {sigup} verified md5sum of maldet-sigpack.tgz
maldet(15488): {sigup} unpacked and installed maldet-sigpack.tgz
maldet(15488): {sigup} verified md5sum of maldet-clean.tgz
maldet(15488): {sigup} unpacked and installed maldet-clean.tgz
maldet(15488): {sigup} signature set update completed
maldet(15488): {sigup} 10822 signatures (8908 MD5 / 1914 HEX / 0 USER)

Reduce installation

Remove cronjobs: First /etc/cron.d/maldet_pub

*/10 * * * * root /usr/local/maldetect/maldet --mkpubpaths >> /dev/null 2>&1

and also /etc/cron.daily/maldet (scan through everything daily, I suppose):

#!/usr/bin/env bash
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH
export LMDCRON=1
. /usr/local/maldetect/conf.maldet
if [ -f "/usr/local/maldetect/conf.maldet.cron" ]; then
	. /usr/local/maldetect/conf.maldet.cron
fi
find=`which find 2> /dev/null`
if [ "$find" ]; then
	# prune any quarantine/session/tmp data older than 7 days
	tmpdirs="/usr/local/maldetect/tmp /usr/local/maldetect/sess /usr/local/maldetect/quarantine /usr/local/maldetect/pub"
	for dir in $tmpdirs; do
	 if [ -d "$dir" ]; then
	  $find $dir -type f -mtime +7 -print0 | xargs -0 rm -f >> /dev/null 2>&1
	 fi
	done
fi

if [ "$autoupdate_version" == "1" ] || [ "$autoupdate_signatures" == "1" ]; then
	# sleep for random 1-999s interval to better distribute upstream load
	sleep $(echo $RANDOM | cut -c1-3) >> /dev/null 2>&1
fi

if [ "$autoupdate_version" == "1" ]; then
	# check for new release version
	/usr/local/maldetect/maldet -d >> /dev/null 2>&1
fi

if [ "$autoupdate_signatures" == "1" ]; then
	# check for new definition set
	/usr/local/maldetect/maldet -u >> /dev/null 2>&1
fi

# if we're running inotify monitoring, send daily hit summary
if [ "$(ps -A --user root -o "cmd" | grep maldetect | grep inotifywait)" ]; then
        /usr/local/maldetect/maldet --monitor-report >> /dev/null 2>&1
else
	if [ -d "/home/virtual" ] && [ -d "/usr/lib/opcenter" ]; then
		# ensim
	        /usr/local/maldetect/maldet -b -r /home/virtual/?/fst/var/www/html/,/home/virtual/?/fst/home/?/public_html/ 1 >> /dev/null 2>&1
	elif [ -d "/etc/psa" ] && [ -d "/var/lib/psa" ]; then
		# psa
		/usr/local/maldetect/maldet -b -r /var/www/vhosts/?/ 1 >> /dev/null 2>&1
        elif [ -d "/usr/local/directadmin" ]; then
                # DirectAdmin
                /usr/local/maldetect/maldet -b -r /home?/?/domains/?/public_html/,/var/www/html/?/ 1 >> /dev/null 2>&1
	elif [ -d "/var/www/clients" ]; then
		# ISPConfig
                /usr/local/maldetect/maldet -b -r /var/www/clients/?/web?/web 1 >> /dev/null 2>&1
	elif [ -d "/etc/webmin/virtual-server" ]; then
		# Virtualmin
                /usr/local/maldetect/maldet -b -r /home/?/public_html/,/home/?/domains/?/public_html/ 1 >> /dev/null 2>&1
	elif [ -d "/usr/local/ispmgr" ]; then
		# ISPmanager
		/usr/local/maldetect/maldet -b -r /var/www/?/data/,/home/?/data/ 1 >> /dev/null 2>&1
	elif [ -d "/var/customers/webs" ]; then
		# froxlor
		/usr/local/maldetect/maldet -b -r /var/customers/webs/ 1 >> /dev/null 2>&1
	else
		# cpanel, interworx and other standard home/user/public_html setups
	        /usr/local/maldetect/maldet -b -r /home?/?/public_html/,/var/www/html/,/usr/local/apache/htdocs/ 1 >> /dev/null 2>&1
	fi
fi

And then remove the bootup hooks (I could and should have done this with chkconfig, actually):

# rm `find /etc/rc.d/ -iname S\*maldet\*`
rm: remove symbolic link `/etc/rc.d/rc3.d/S70maldet'? y
rm: remove symbolic link `/etc/rc.d/rc4.d/S70maldet'? y
rm: remove symbolic link `/etc/rc.d/rc2.d/S70maldet'? y
rm: remove symbolic link `/etc/rc.d/rc5.d/S70maldet'? y

Configuration

Edit /usr/local/maldetect/conf.maldet. The file is self-explained. The defaults are quite non-intrusive (no quarantine nor cleaning by default, no user suspension etc.). I turned off the automatic updates (I don’t run this as a cron job anyhow) and opted in scans by users:

scan_user_access="1"

Other than that, I kept it as is.

Preparing for run as non-root user

As a regular user (“eli”) I went

$ maldet
touch: cannot touch `/usr/local/maldetect/pub/eli/event_log': No such file or directory
/usr/local/maldetect/internals/functions: line 31: cd: /usr/local/maldetect/pub/eli/tmp: No such file or directory
mkdir: cannot create directory `/usr/local/maldetect/pub/eli': Permission denied
chmod: cannot access `/usr/local/maldetect/pub/eli/tmp': No such file or directory
mkdir: cannot create directory `/usr/local/maldetect/pub/eli': Permission denied
chmod: cannot access `/usr/local/maldetect/pub/eli/sess': No such file or directory
mkdir: cannot create directory `/usr/local/maldetect/pub/eli': Permission denied
chmod: cannot access `/usr/local/maldetect/pub/eli/quar': No such file or directory
sed: couldn't open temporary file /usr/local/maldetect/sedIuE2ll: Permission denied

[...]

So it expects a directory accessible by non-root self. Let’s make one (as root)

# cd /usr/local/maldetect/pub/
# mkdir eli
# chown eli:eli eli

Giving it a try

Try

$ maldet -h

And performing a scan (checking a specific sub-directory on my Desktop):

$ maldet -a /home/eli/Desktop/hacked/
sed: couldn't open temporary file /usr/local/maldetect/sedcSyxa1: Permission denied
Linux Malware Detect v1.5
            (C) 2002-2015, R-fx Networks <proj@rfxn.com>
            (C) 2015, Ryan MacDonald <ryan@rfxn.com>
This program may be freely redistributed under the terms of the GNU GPL v2

ln: creating symbolic link `/usr/local/maldetect/sigs/lmd.user.ndb': Permission denied
ln: creating symbolic link `/usr/local/maldetect/sigs/lmd.user.hdb': Permission denied
/usr/local/maldetect/internals/functions: line 1647: /usr/local/maldetect/tmp/.runtime.hexsigs.18117: Permission denied
maldet(18117): {scan} signatures loaded: 10822 (8908 MD5 / 1914 HEX / 0 USER)
maldet(18117): {scan} building file list for /home/eli/Desktop/hacked/, this might take awhile...
maldet(18117): {scan} setting nice scheduler priorities for all operations: cpunice 19 , ionice 6
maldet(18117): {scan} file list completed in 0s, found 8843 files...
maldet(18117): {scan} scan of /home/eli/Desktop/hacked/ (8843 files) in progress...
maldet(18117): {scan} 8843/8843 files scanned: 0 hits 0 cleaned
maldet(18117): {scan} scan completed on /home/eli/Desktop/hacked/: files 8843, malware hits 0, cleaned hits 0, time 253s
maldet(18117): {scan} scan report saved, to view run: maldet --report 151231-0915.18117

Uh, that was really bad. The directory contains several malware PHP files. Maybe the signature isn’t updated? The file my hosting provider detected was quarantined, and those that were left are probably sophisticated enough to go under the radar.

Update the signature file

Since I turned off the automatic update of signature files, I have to do this manually. As root,

# maldet -u
Linux Malware Detect v1.5
            (C) 2002-2015, R-fx Networks <proj@rfxn.com>
            (C) 2015, Ryan MacDonald <ryan@rfxn.com>
This program may be freely redistributed under the terms of the GNU GPL v2

maldet(15175): {sigup} performing signature update check...
maldet(15175): {sigup} local signature set is version 2015121610247
maldet(15175): {sigup} latest signature set already installed

Well, no wonder, I just installed maldet.

So the bottom line, mentioned above, is that this tool isn’t all that effective against the specific malware I got.

Reader Comments

Did you submit your samples to the project so that it can detect this malware in the future?

#1 
Written By Emily on February 5th, 2016 @ 01:26

I pretty much doubt it would help. This type of malware seems to be aware of signature-based detection software, and therefore works around it. Odds are that the developers are know this sort already, but decided against making the efforts needed to detecting it.

#2 
Written By eli on February 5th, 2016 @ 09:27
#3 
Written By Phil on April 11th, 2017 @ 12:35

Add a Comment

required, use real name
required, will not be published
optional, your blog address