Linux: Malware Scanner

Anleitung zum Einsatz von ClamAV mit zusätzlichen Signatur-Datenbanken von Linux Malware Detect (GitHub) und Sanesecurity.

ClamAV

Installation

sudo aptitude install clamav clamav-daemon

Anpassungen

systemd

/etc/clamav/clamd.conf
PidFile /run/clamav/clamd.pid
sudo systemctl stop clamav-daemon.service
sudo rmdir /run/clamav
sudo cp /lib/systemd/system/clamav-daemon.service /etc/systemd/system/
sudo systemctl daemon-reload
/etc/systemd/system/clamav-daemon.socket
[Unit]
Description=Clam AntiVirus Socket
ConditionPathExistsGlob=/var/lib/clamav/main.{c[vl]d,inc}
ConditionPathExistsGlob=/var/lib/clamav/daily.{c[vl]d,inc}
 
[Socket]
ListenStream=/run/clamav/clamd.ctl
SocketUser=clamav
SocketGroup=clamav
RemoveOnStop=false
 
[Install]
WantedBy=sockets.target
/etc/systemd/system/clamav-daemon.service
[Unit]
Description=Clam AntiVirus Daemon
After=local-fs.target
Requires=clamav-daemon.socket
ConditionPathExistsGlob=/var/lib/clamav/main.{c[vl]d,inc}
ConditionPathExistsGlob=/var/lib/clamav/daily.{c[vl]d,inc}
 
[Service]
Type=simple
User=clamav
RuntimeDirectory=clamav
PIDFile=/run/clamav/clamd.pid
PermissionsStartOnly=true
ExecStart=/usr/sbin/clamd -c /etc/clamav/clamd.conf --foreground=true
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure
RestartSec=10s
StandardError=null
StandardOutput=syslog
RestrictAddressFamilies=AF_INET AF_UNIX
RestrictRealtime=true
RestrictNamespaces=true
PrivateTmp=true
PrivateDevices=true
PrivateUsers=true
ProtectHome=true
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectSystem=strict
ProtectControlGroups=true
MemoryDenyWriteExecute=true
RemoveIPC=false
InaccessiblePaths=/boot /root
ReadWritePaths=/var/lib/clamav /var/log/clamav
NoNewPrivileges=true
CapabilityBoundingSet=CAP_SETUID CAP_SETGID CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH
SystemCallArchitectures=x86-64
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @privileged @raw-io ptrace
 
[Install]
WantedBy=multi-user.target
Also=clamav-daemon.socket
sudo systemctl start clamav-daemon.service

AppArmor

ClamAV funktioniert mit AppArmor nicht einwandfrei.

sudo ln -s /etc/apparmor.d/usr.sbin.clamd /etc/apparmor.d/disable/usr.sbin.clamd
sudo ln -s /etc/apparmor.d/usr.bin.freshclam /etc/apparmor.d/disable/usr.bin.freshclam

Download von Signatur-Datenbanken

Damit auch die Signaturen des Google Safebrowsing Dienstes verwendet werden, muss die /etc/clamav/freshclam.conf um die entsprechende Option ergänzt werden. Wer den Download der Signatur-Datenbanken über einen Proxy leiten lassen will, ergänzt die entsprechenden Optionen. Außerdem sollte man einen lokal gelegenen Mirror bevorzugen.

/etc/clamav/freshclam.conf
SafeBrowsing yes
DatabaseMirror db.de.clamav.net
HTTPProxyServer host.domain.tld
HTTPProxyPort port

Zusätzliche Signatur-Datenbanken

Neben den Signaturen von ClamAV kann man zusätzliche (nicht offizielle) Signaturen von Linux Malware Detect und Sanesecurity einbinden. Wer die Signatur-Datenbanken einbindet, kann die obige systemd Unit-Datei ergänzen, um die Ausgabe von Fehler- und Warnmeldungen zu unterdrücken, die sich aufgrund mit ClamAV inkompatibler Inhalte in den Datenbanken ergeben können. Läuft der clamd Daemon mal nicht, kann man temporär die Ergänzung zwecks Fehlersuche wieder auskommentieren und/oder/bzw. die OfficialDatabaseOnly false Option in der /etc/clamav/clamd.conf Datei setzen.

/etc/systemd/system/clamav-daemon.service
[Service]
StandardError=null

Download, Aktualisierung und Einpflegen der Datenbanken kann man über Skripte durchführen. Als Debian-Paket ist clamav-unofficial-sigs verfügbar:

sudo aptitude install clamav-unofficial-sigs

Ein darauf basierendes und weiter gepflegtes Skript ist das gleichnamige clamav-unofficial-sigs Skript von eXtremeSHOK.

Alternativ kann man das folgende clamav-3dparty-update Skript verwenden, das etwas einfacher gehalten ist und Signatur-Datenbanken von LMD und Sanesecurity (mit niedriger und mittlerer False Positives Rate) herunterlädt und aktualisiert. Für das Skript werden GnuPG 2, git, rsync und curl benötigt. Die Downloads werden über den Proxy weitergeleitet, der in der RSYNC_PROXY Variable steht (hier: PrivoxyTor). Wer keinen Proxy verwendet, muss die Variable auskommentieren und die Aufrufe von curl und git im Skript entsprechend ändern:

# RSYNC_PROXY="host.domain.tld:port"
# export RSYNC_PROXY
--proxy $RSYNC_PROXY für curl entfernen
-c http.proxy=$RSYNC_PROXY für git entfernen

Vor dem ersten Start wird git installiert – die anderen genannten Anwendungen müssten bereits automatisch installiert worden sein – und die Verzeichnisstruktur angelegt:

sudo aptitude install git
sudo mkdir -p /var/lib/clamav-3dparty/{lmd/tmp,sanesecurity/gpg,sanesecurity-bad,yararules,yararules-bad}
sudo chmod 700 /var/lib/clamav-3dparty/sanesecurity/gpg
sudo chown -R clamav:clamav /var/lib/clamav-3dparty/
/usr/local/bin/clamav-3dparty-update
#!/bin/sh
################################################################
# Script to download and update additional Sanesecurity and LMD
# signatures for ClamAV
# V. 1.1
# Copyright 2018 K. Raven <kraven@secure.mailbox.org>
# License: BSD-2-Clause License
#          <https://opensource.org/licenses/bsd-license.php>
################################################################
 
clamdb_dir="/var/lib/clamav"
dbs_dir="/var/lib/clamav-3dparty"
ss_dir="$dbs_dir/sanesecurity"
ss_gpg_dir="$ss_dir/gpg"
ss_dblist="$ss_dir/ss-rsync"
ss_url="rsync.sanesecurity.net"
ss_mirror_ips="$(dig +ignore +short "$ss_url")"
ss_gpg_url="http://www.sanesecurity.net/publickey.gpg"
lmd_base_url="https://cdn.rfxn.com/downloads"
lmd_sigver_file="maldet.sigs.ver"
lmd_sigver_url="$lmd_base_url/$lmd_sigver_file"
lmd_sig_file="maldet-sigpack.tgz"
lmd_sig_url="$lmd_base_url/$lmd_sig_file"
lmd_dir="$dbs_dir/lmd"
lmd_dir_tmp="$lmd_dir/tmp"
RSYNC_PROXY="sub.domain.tld:8118"
export RSYNC_PROXY
curl="curl --silent --connect-timeout 60 --retry 3 --location --remote-name"
 
if [ -z "$ss_mirror_ips" ] ; then
  ss_mirror_ips=$(host -t A "$ss_url" | sed -n '/has address/{s/.*address \([^ ]*\).*/\1/;p;}')
fi
 
trap "rm $ss_dblist $ss_dir/mirror_ips" EXIT
 
for i in $ss_mirror_ips; do
  if [ "$(ping -c 1 -n -q $i >/dev/null ; echo $?)" = "0" ]; then
    echo "$i" >> $ss_dir/mirror_ips
  fi
done
 
ss_mirror_ip="$(cat $ss_dir/mirror_ips | shuf -n1)"
 
if [ ! -f $ss_gpg_dir/pubring.kbx ]; then
  cd $ss_gpg_dir && \
  $curl --proxy $RSYNC_PROXY $ss_gpg_url -o publickey.gpg && \
  gpg -q --no-options --no-default-keyring --homedir $ss_gpg_dir --keyring $ss_gpg_dir/pubring.kbx --import $ss_gpg_dir/publickey.gpg
fi
 
sleep 3
 
# Sanesecurity signatures
 
# low+med fp risk dbs
# http://sanesecurity.com/usage/signatures/
# list dbs:
# rsync --list-only "rsync://$ss_mirror_ip/sanesecurity"
 
ss_dbs="
junk.ndb
jurlbl.ndb
jurlbla.ndb
lott.ndb
phish.ndb
rogue.hdb
sanesecurity.ftm
sigwhitelist.ign2
scam.ndb
spam.ldb
spamimg.hdb
spamattach.hdb
spear.ndb
spearl.ndb
blurl.ndb
foxhole_generic.cdb
foxhole_filename.cdb
foxhole_js.ndb
malwarehash.hsb
hackingteam.hsb
badmacro.ndb
shelter.ldb
winnow_malware.hdb
winnow_malware_links.ndb
winnow_spam_complete.ndb
winnow_phish_complete_url.ndb
winnow.complex.patterns.ldb
winnow_extended_malware.hdb
winnow_extended_malware_links.ndb
winnow.attachments.hdb
winnow_bad_cw.hdb
MiscreantPunch099-Low.ldb
scamnailer.ndb
bofhland_cracked_URL.ndb
bofhland_malware_URL.ndb
bofhland_phishing_URL.ndb
bofhland_malware_attach.hdb
phishtank.ndb"
 
for db in $ss_dbs ; do
  echo "$db" >> "$ss_dblist"
  echo "$db.sig" >> "$ss_dblist"
done
 
rsync --quiet --no-motd --contimeout=60 --files-from="$ss_dblist" --timeout=60 "rsync://$ss_mirror_ip/sanesecurity" $ss_dir/ 2>/dev/null
 
cd $ss_dir/ && \
for db in $ss_dbs ; do
   chmod 640 "$db"*
   status="$(gpg --no-options --trust-model always --no-default-keyring --homedir $ss_gpg_dir/ --keyring $ss_gpg_dir/pubring.kbx -q --no-tty --no-verbose --status-fd 1 --verify "$db".sig 2>/dev/null | egrep "^\[GNUPG:\] VALIDSIG" | cut -d\  -f 2)" ; \
   dbtest="$(clamscan --quiet --stdout -d "$db" 2>/dev/null | egrep "^ERROR: Malformed database")"
   if [ "$status" = "VALIDSIG" -a "$dbtest" != "ERROR: Malformed database" ] ; then
     cp -f "$db" $clamdb_dir/
   else 
     ln -s $ss_dir/"$db" $dbs_dir/sanesecurity-bad/ 2>/dev/null ; ln -s $ss_dir/"$db".sig $dbs_dir/sanesecurity-bad/ 2>/dev/null
   fi
done
 
# LMD signatures
 
cd $lmd_dir_tmp
 
$curl --proxy $RSYNC_PROXY $lmd_sigver_url
 
if [ -f "$lmd_dir/$lmd_sigver_file" -a -f "$lmd_dir_tmp/$lmd_sigver_file" ]; then
  if [ "$(cat $lmd_dir/$lmd_sigver_file)" = "$(cat $lmd_dir_tmp/$lmd_sigver_file)" ]; then
    echo "" >/dev/null
  fi
else
  cd $lmd_dir
  cp -f $lmd_dir_tmp/$lmd_sigver_file .
  $curl --proxy $RSYNC_PROXY $lmd_sig_url && \
  tar -xzf $lmd_sig_file && \
  cd sigs && \
  cp -f rfxn.hdb rfxn.ndb rfxn.yara $clamdb_dir
fi
 
sleep 3
 
clamdscan --reload
 
exit 0

Nachdem das Skript gespeichert und ausführbar gemacht wurde, wird noch ein Cron-Job angelegt:

6 */6 * * * clamav [ -x /usr/local/bin/clamav-3dparty-update ] && /usr/local/bin/clamav-3dparty-update

Anwendung

manuell

clamdscan -m -z --fdpass oder --stream Datei|Verzeichnis

automatisch

Man kann den clamd mit entsprechenden Optionen in der clamd.conf „OnAccess“ per fanotify Verzeichnisse überwachen und scannen lassen, bekommt aber Probleme, wenn der clamd mit eigenem clamav Benutzer läuft. Stattdessen werden Verzeichnisse und Dateien mit iwatch per fanotify überwacht und bei Ereignissen wie der Neuanlage oder Veränderung von Dateien ein Skript aufgerufen, das die Dateien per clamdscan dem clamd Daemon zu scannen meldet und bei einem Malware-Fund eine entsprechende E-Mail absetzt.

iwatch Installation
sudo aptitude install iwatch
iwatch Konfiguration
sudo vi /etc/iwatch/iwatch.xml
iwatch.xml
<?xml version="1.0" ?>
<!DOCTYPE config SYSTEM "iwatch.dtd">
 
<config>
 <guard email="name@host.domain.tld" name="iwatch"></guard>
 <watchlist>
 <title>clamdscan</title>
 <contactpoint email="name@host.domain.tld" name="admin"/>
  <path type="recursive" events="create" alert="off" exec="/usr/local/bin/clamd_event '%f'">/pfad/dir1</path> 
  <path type="recursive" events="create" alert="off" exec="/usr/local/bin/clamd_event '%f'">/pfad/dir2</path>
  <path type="recursive" events="default" alert="off" exec="/usr/local/bin/clamd_event '%f'">/pfad/download</path>
  <path type="regexception">(\.part|\.swp|datei1\.ext|datei2\.ext)</path>
  <path type="recursive" events="create" alert="off" exec="/usr/local/bin/clamd_event '%f'">/tmp</path>
  <path type="regexception">^incomplete.*\.(mp3|m4a|flac)</path>
  <path type="recursive" events="create" alert="off" exec="/usr/local/bin/clamd_event '%f'">/var/tmp</path>
  <path type="single" events="default" alert="off" exec="/usr/local/bin/clamd_event '%f'">/var/cache/apt/archives</path>
 </watchlist>
</config>

Ausnahmen für Verzeichnisinhalte werden direkt unter die Regel für das Verzeichnis gesetzt – entweder mit dem regexception Typ für RegEx-Muster oder exception Typ für absolute Pfadangaben zu einzelnen Dateien oder Unterverzeichnissen.

Scan-Skript
clamd_event
#!/bin/sh
 
# für UID die uid des Benutzers einsetzen, der clamdscan ausführen soll
 
scan="$(sudo -H -u \#UID clamdscan -m -z --no-summary --fdpass "$1")"
result="$(echo "$scan" | grep -c FOUND)"
 
if [ $result = 1 ]; then
 echo "Clamdscan-Resultat:\n$scan" | mail -s "[clamdscan] Alarm" root	
else
 exit 0
fi
 
exit 0

Verweise auf aktuelle Seite