Linux Malware Detect for occasional non-root use
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: 0FILE 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?
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.
Give https://github.com/Neohapsis/NeoPI a try.