ClamAV can be used in a few different ways. Most importantly, it provides the ability to scan files in realtime (on-access) or to scan the file system periodically.
I tried configuring ClamAV to both perform on-access virus scanning and to perform nightly full filesystem scanning. Using the on-access option did not prove to be very useful, however a scheduled full system scan seems to be of value.
Here is my story.
This is pretty straight forward. I installed clamav
, clamscan
, and clamav-daemon
$ sudo apt-get install clamav clamscan clamav-daemon
ClamAV comes with on-access scanning. I attempted to configure the ClamAV daemon to scan accessed files. My goal was to log and notify potential vulnerabilities. Additionally, ClamAV can be configured to interact with potential vulnerabilities directly - however I would not personally be comfortable with such an implementation on my systems, and have opted to skip this.
The ClamAV daemon does not start on-access scanning automatically. In order to facilitate this, I decided to create a system daemon to run the clamonacc
script automatically.
I identified two large issues with on-access scanning:
- Very verbose logging of access errors (tens of thousands of lines per hour)
- Notifications are broken
Update the clamd configuration file. This is located in /etc/clamav/clamd.conf
ExtendedDetectionInfo yes
FixStaleSocket yes
LocalSocket /var/run/clamav/clamd.ctl
LogFile /var/log/clamav/clamav.log
LogFileMaxSize 5M
LogRotate yes
LogTime yes
MaxDirectoryRecursion 15
MaxThreads 20
OnAccessExcludeUname clamav
OnAccessExcludeUname root
OnAccessIncludePath /home
OnAccessMountPath /home/johnfedoruk
OnAccessPrevention yes
User root
VirusEvent /etc/clamav/detected.sh
Add a notifitcation script to /etc/clamav/detected.sh
and make sure it's executable with a chmod +x
#!/bin/bash
export LOG="/var/log/clamav/scan.log"
export TARGET="/"
export SUMMARY_FILE=`mktemp`
export SCAN_STATUS
export INFECTED_SUMMARY
export XUSERS
echo "------------ SCAN START ------------" >> "$LOG"
echo "Running scan on `date`" >> "$LOG"
sudo clamdscan --log "$LOG" --infected --multiscan --fdpass "$TARGET" > "$SUMMARY_FILE"
SCAN_STATUS="$?"
INFECTED_SUMMARY=`cat $SUMMARY_FILE | grep Infected`
rm "$SUMMARY_FILE"
if [[ "$SCAN_STATUS" -ne "0" ]] ; then
# Send the alert to systemd logger if exist
if [[ -n $(command -v systemd-cat) ]] ; then
echo "Virus signature found - $INFECTED_SUMMARY" | /usr/bin/systemd-cat -t clamav -p emerg
fi
# Send an alert to all graphical users.
XUSERS=($(who|awk '{print $1$NF}'|sort -u))
for XUSER in $XUSERS; do
NAME=(${XUSER/(/ })
DISPLAY=${NAME[1]/)/}
DBUS_ADDRESS=unix:path=/run/user/$(id -u ${NAME[0]})/bus
echo "run $NAME - $DISPLAY - $DBUS_ADDRESS -" >> /tmp/testlog
/usr/bin/sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \
DBUS_SESSION_BUS_ADDRESS=${DBUS_ADDRESS} \
PATH=${PATH} \
/usr/bin/notify-send -i security-low "Virus signature(s) found" "$INFECTED_SUMMARY"
done
fi
Now restart the service
$ sudo systemctl restart clamav-daemon.service
And get the status
$ sudo systemctl status clamav-daemon.service
● clamav-daemon.service - Clam AntiVirus userspace daemon
Loaded: loaded (/lib/systemd/system/clamav-daemon.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/clamav-daemon.service.d
└─extend.conf
Active: active (running) since Thu 2020-03-26 15:32:22 CDT; 40min ago
Docs: man:clamd(8)
man:clamd.conf(5)
https://www.clamav.net/documents/
Process: 32756 ExecStartPre=/bin/mkdir /run/clamav (code=exited, status=1/FAILURE)
Process: 32759 ExecStartPre=/bin/chown clamav /run/clamav (code=exited, status=0/SUCCESS)
Main PID: 32760 (clamd)
Tasks: 5 (limit: 4915)
Memory: 911.8M
CGroup: /system.slice/clamav-daemon.service
└─32760 /usr/sbin/clamd --foreground=true
Now add a Systemd configuration. Add it to a new file /etc/systemd/system/clamav-onacc.service
.
[Unit]
Description=ClamAV On Access Scanner
Requires=clamav-daemon.service
After=clamav-daemon.service syslog.target network.target
[Service]
Type=simple
User=root
ExecStart=/usr/bin/clamonacc -F
Restart=on-failure
RestartSec=120s
[Install]
WantedBy=multi-user.target
And now enable the new service
$ sudo systemctl enable clamav-onacc.service
Start the new service
$ sudo systemctl start clamav-onacc.service
And get the status
$ sudo systemctl status clamav-onacc.service
● clamav-onacc.service - ClamAV On Access Scanner
Loaded: loaded (/etc/systemd/system/clamav-onacc.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2020-03-26 15:33:25 CDT; 41min ago
Main PID: 1789 (clamonacc)
Tasks: 7 (limit: 4915)
Memory: 11.6M
CGroup: /system.slice/clamav-onacc.service
└─1789 /usr/bin/clamonacc -F --log=/var/log/clamav/access.log
Logging was configured in /var/log/clamav/clamav.log
. We can see that once started, it immediatly starts filling with garbage access errors.
Thu Mar 26 15:33:32 2020 -> /var/snap/microk8s/1247/certs/front-proxy-client.crt: Can't open file or directory ERROR
Thu Mar 26 15:33:32 2020 -> /var/snap/microk8s/1247/certs/front-proxy-client.crt: Can't open file or directory ERROR
Thu Mar 26 15:33:32 2020 -> /var/snap/microk8s/1247/certs/front-proxy-client.crt: Can't open file or directory ERROR
Thu Mar 26 15:33:32 2020 -> /var/snap/microk8s/1247/certs/front-proxy-client.crt: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/bin/sudo: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/bin/sudo: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/share/icons/Pop/scalable/status/network-wireless-signal-good-symbolic.svg: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/share/icons/Pop/scalable/status/network-wireless-signal-good-symbolic.svg: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/share/icons/Pop/scalable/status/network-wireless-signal-good-symbolic.svg: Can't open file or directory ERROR
Thu Mar 26 15:33:36 2020 -> /usr/share/icons/Pop/scalable/status/network-wireless-signal-good-symbolic.svg: Can't open file or directory ERROR
Thu Mar 26 15:33:37 2020 -> /usr/bin/sudo: Canjohnfedorukstem76-power.conf: Can't open file or directory ERROR
Thu Mar 26 15:33:40 2020 -> /etc/fstab: Can't open file or directory ERROR
Thu Mar 26 15:33:40 2020 -> /etc/fstab: Can't open file or directory ERROR
Thu Mar 26 15:33:50 2020 -> /usr/bin/clamonacc: Can't open file or directory ERROR
Thu Mar 26 15:33:52 2020 -> /usr/bin/clamonacc: Can't open file or directory ERROR
Thu Mar 26 15:33:53 2020 -> /usr/bin/sudo: Can't open file or directory ERROR
Thu Mar 26 15:33:53 2020 -> /usr/bin/sudo: Can't open file or directory ERROR
Thu Mar 26 15:33:59 2020 -> WARNING: lstat() failed on: /home/johnfedoruk/.config/Microsoft/Microsoft Teams/Cache/index-dir/temp-index
Thu Mar 26 15:33:59 2020 -> WARNING: lstat() failed on: /home/johnfedoruk/.config/Microsoft/Microsoft Teams/Cache/index-dir/temp-index
If we cat an eicar test file, we can see that this is found by the anti-virus and logged. However, again, it is burried in garbage output.
Look for the line Thu Mar 26 15:36:50 2020 -> /home/johnfedoruk/Downloads/eicar.com: Win.Test.EICAR_HDB-1(44d88612fea8a8f36de82e1278abb02f:68) FOUND
.
Thu Mar 26 15:36:49 2020 -> /usr/share/icons/Pop/scalable/actions/edit-find-symbolic.svg: Can't open file or directory ERROR
Thu Mar 26 15:36:49 2020 -> /usr/bin/cat: Can't open file or directory ERROR
Thu Mar 26 15:36:49 2020 -> /usr/bin/cat: Can't open file or directory ERROR
Thu Mar 26 15:36:49 2020 -> /usr/bin/cat: Can't open file or directory ERROR
Thu Mar 26 15:36:49 2020 -> /home/johnfedoruk/Downloads/eicar.com: Win.Test.EICAR_HDB-1(44d88612fea8a8f36de82e1278abb02f:68) FOUND
Thu Mar 26 15:36:50 2020 -> /usr/bin/cat: Can't open file or directory ERROR
Thu Mar 26 15:36:50 2020 -> /usr/bin/cat: Can't open file or directory ERROR
Thu Mar 26 15:36:50 2020 -> /home/johnfedoruk/Downloads/eicar.com: Win.Test.EICAR_HDB-1(44d88612fea8a8f36de82e1278abb02f:68) FOUND
Thu Mar 26 15:36:50 2020 -> /var/snap/microk8s/1247/args/kube-apiserver: Can't open file or directory ERROR
Thu Mar 26 15:36:58 2020 -> WARNING: lstat() failed on: /home/johnfedoruk/.config/Microsoft/Microsoft Teams/Cache/index-dir/temp-index
The log files quickly fill with thousands upon thousands of errors related to failed access of virtual and otherwise inaccessible files. Running SSDs in RAID 0 on a machine that never shuts down makes me uncomfortable with such verbose logging.
No matter what I did, I could not get the clamd.conf
VirusEvent directive to work.
Reading the source, it becomes clear that the issue is with line 83 of the code as of version v0.100
(and removed completely in the latest stable versions)
/* TODO : FIXME? virusaction forks. This could be extraordinarily problematic, lead to deadlocks,
* or at the very least lead to extreme memory consumption. Leaving disabled for now.*/
//virusaction(fname, virname, tharg->opts);
While it would be possible to downgrade the ClamAV tool, or to reimplement and recompile the now missing onaccess_fan.c
file into the tool - it seems unwise to overlook the developer's warning.
ClamAV comes with clamdscan. I attempted to configure ClamAV daemon to scan all filesystem files and generate a report once a day. My goal was to log and notify potential vulnerabilities. Additionally, ClamAV can be configured to interact with potential vulnerabilities directly - however I would not personally be comfortable with such an implementation on my systems, and have opted to skip this.
The ClamAV daemon does not start a filesystem scanning automatically. In order to facilitate this, I decided to create a systemd timer to run the clamdscan
script automatically.
Update the clamd configuration file. This is located in /etc/clamav/clamd.conf
ExcludePath ^/dev/
ExcludePath ^/proc/
ExcludePath ^/sys/
ExtendedDetectionInfo yes
FixStaleSocket yes
LocalSocket /var/run/clamav/clamd.ctl
LogTime yes
MaxDirectoryRecursion 0
MaxThreads 32
User root
Now restart the service
$ sudo systemctl restart clamav-daemon.service
And get the status
$ sudo systemctl status clamav-daemon.service
● clamav-daemon.service - Clam AntiVirus userspace daemon
Loaded: loaded (/lib/systemd/system/clamav-daemon.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/clamav-daemon.service.d
└─extend.conf
Active: active (running) since Thu 2020-03-26 15:32:22 CDT; 40min ago
Docs: man:clamd(8)
man:clamd.conf(5)
https://www.clamav.net/documents/
Process: 32756 ExecStartPre=/bin/mkdir /run/clamav (code=exited, status=1/FAILURE)
Process: 32759 ExecStartPre=/bin/chown clamav /run/clamav (code=exited, status=0/SUCCESS)
Main PID: 32760 (clamd)
Tasks: 5 (limit: 4915)
Memory: 911.8M
CGroup: /system.slice/clamav-daemon.service
└─32760 /usr/sbin/clamd --foreground=true
Add a scan script to /etc/clamav/scan.sh
and make sure it's executable with a chmod +x
#!/bin/bash
export LOG="/var/log/clamav/scan.log"
export TARGET="/"
export SUMMARY_FILE=`mktemp`
export FIFO_DIR=`mktemp -d`
export FIFO="$FIFO_DIR/log"
export SCAN_STATUS
export INFECTED_SUMMARY
export XUSERS
mkfifo "$FIFO"
tail -f "$FIFO" | tee -a "$LOG" "$SUMMARY_FILE" &
echo "------------ SCAN START ------------" > "$FIFO"
echo "Running scan on `date`" > "$FIFO"
echo "Scanning $TARGET" > "$FIFO"
clamdscan --infected --multiscan --fdpass --stdout "$TARGET" | grep -vE 'WARNING|ERROR|^$' > "$FIFO"
echo > "$FIFO"
SCAN_STATUS="${PIPESTATUS[0]}"
INFECTED_SUMMARY=`cat "$SUMMARY_FILE" | grep "Infected files"`
rm "$SUMMARY_FILE"
rm "$FIFO"
rmdir "$FIFO_DIR"
if [[ "$SCAN_STATUS" -ne "0" ]] ; then
# Send the alert to systemd logger if exist
if [[ -n $(command -v systemd-cat) ]] ; then
echo "Virus signature found - $INFECTED_SUMMARY" | /usr/bin/systemd-cat -t clamav -p emerg
fi
# Send an alert to all graphical users.
XUSERS=($(who|awk '{print $1$NF}'|sort -u))
for XUSER in $XUSERS; do
NAME=(${XUSER/(/ })
DISPLAY=${NAME[1]/)/}
DBUS_ADDRESS=unix:path=/run/user/$(id -u ${NAME[0]})/bus
echo "run $NAME - $DISPLAY - $DBUS_ADDRESS -" >> /tmp/testlog
/usr/bin/sudo -u ${NAME[0]} DISPLAY=${DISPLAY} \
DBUS_SESSION_BUS_ADDRESS=${DBUS_ADDRESS} \
PATH=${PATH} \
/usr/bin/notify-send -i security-low "Virus signature(s) found" "$INFECTED_SUMMARY"
done
fi
Now add a Systemd service and timer configuration.
Add the service to a new file /etc/systemd/system/clamav-scan.service
[Unit]
Description=ClamAV System Scanner
Requires=clamav-daemon.service
[Service]
Type=simple
User=root
ExecStart=/etc/clamav/scan.sh
[Install]
WantedBy=multi-user.target
Add the timer to /etc/systemd/system/clamav-scan.timer
[Unit]
Description=ClamAV System Scanner
Requires=clamav-daemon.service
[Timer]
OnCalendar=
OnCalendar=*-*-* 23:11:00
Persistent=false
Unit=clamav-scan.service
[Install]
WantedBy=timers.target
Enable the timer
$ sudo systemctl enable clamav-scan.timer
Start the timer
$ sudo systemctl start clamav-scan.timer
And verify the status of the timer
$ sudo systemctl status clamav-scan.timer
● clamav-scan.timer - ClamAV System Scanner
Loaded: loaded (/etc/systemd/system/clamav-scan.timer; enabled; vendor preset: enabled)
Active: active (elapsed) since Thu 2020-03-26 19:12:05 CDT; 7min ago
Trigger: n/a
Mar 26 19:12:05 workstation systemd[1]: Started ClamAV System Scanner.
Viewing the logs for a full system scan, if configured correctly, is very easy. By using systemd timers, we have the benefit of viewing the status of the last scan using systemctl. For example
$ sudo systemctl status clamav-scan.service
● clamav-scan.service - ClamAV System Scanner
Loaded: loaded (/etc/systemd/system/clamav-scan.service; disabled; vendor preset: enabled)
Active: inactive (dead) since Thu 2020-03-26 22:17:45 CDT; 9min ago
Process: 24222 ExecStart=/etc/clamav/scan.sh (code=exited, status=0/SUCCESS)
Main PID: 24222 (code=exited, status=0/SUCCESS)
Mar 26 23:11:00 workstation scan.sh[24222]: ------------ SCAN START ------------
Mar 26 23:11:00 workstation scan.sh[24222]: Running scan on Thu 26 Mar 2020 10:01:00 PM CDT
Mar 26 23:11:00 workstation scan.sh[24222]: Scanning /
Mar 26 22:17:45 workstation scan.sh[24222]: /home/johnfedoruk/Downloads/eicar.com.txt: Win.Test.EICAR_HDB-1 FOUND
Mar 26 22:17:45 workstation scan.sh[24222]: ----------- SCAN SUMMARY -----------
Mar 26 22:17:45 workstation scan.sh[24222]: Infected files: 15
Mar 26 22:17:45 workstation scan.sh[24222]: Time: 345.011 sec (5 m 45 s)
Mar 26 22:17:45 workstation systemd[1]: clamav-scan.service: Succeeded.
We also have the ability to view the history of the logs stored in /var/log/clamav/scan.log
, as configured in our script /etc/clamav/scan.sh
------------ SCAN START ------------
Running scan on Thu 26 Mar 2020 09:45:00 PM CDT
Scanning /
----------- SCAN SUMMARY -----------
Infected files: 0
Time: 330.231 sec (5 m 30 s)
------------ SCAN START ------------
Running scan on Thu 26 Mar 2020 10:01:00 PM CDT
Scanning /
/home/johnfedoruk/Downloads/eicar.com.txt: Win.Test.EICAR_HDB-1 FOUND
----------- SCAN SUMMARY -----------
Infected files: 1
Time: 345.011 sec (5 m 45 s)
Both of these log formats clearly showing any potentially infected files and a concise summary.
When viruses are found, a notification is registered with the GNOME notification center if I am logged into my system. This works exactly as I would expect.
Interesting.
Ran the script through shellcheck, here is the result: